1d5ac70f0Sopenharmony_ci/*
2d5ac70f0Sopenharmony_ci *  PCM - Params functions
3d5ac70f0Sopenharmony_ci *  Copyright (c) 2000 by Abramo Bagnara <abramo@alsa-project.org>
4d5ac70f0Sopenharmony_ci *
5d5ac70f0Sopenharmony_ci *
6d5ac70f0Sopenharmony_ci *   This library is free software; you can redistribute it and/or modify
7d5ac70f0Sopenharmony_ci *   it under the terms of the GNU Lesser General Public License as
8d5ac70f0Sopenharmony_ci *   published by the Free Software Foundation; either version 2.1 of
9d5ac70f0Sopenharmony_ci *   the License, or (at your option) any later version.
10d5ac70f0Sopenharmony_ci *
11d5ac70f0Sopenharmony_ci *   This program is distributed in the hope that it will be useful,
12d5ac70f0Sopenharmony_ci *   but WITHOUT ANY WARRANTY; without even the implied warranty of
13d5ac70f0Sopenharmony_ci *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14d5ac70f0Sopenharmony_ci *   GNU Lesser General Public License for more details.
15d5ac70f0Sopenharmony_ci *
16d5ac70f0Sopenharmony_ci *   You should have received a copy of the GNU Lesser General Public
17d5ac70f0Sopenharmony_ci *   License along with this library; if not, write to the Free Software
18d5ac70f0Sopenharmony_ci *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
19d5ac70f0Sopenharmony_ci *
20d5ac70f0Sopenharmony_ci */
21d5ac70f0Sopenharmony_ci
22d5ac70f0Sopenharmony_ci#include "pcm_local.h"
23d5ac70f0Sopenharmony_ci
24d5ac70f0Sopenharmony_ci#ifndef NDEBUG
25d5ac70f0Sopenharmony_ci/*
26d5ac70f0Sopenharmony_ci * dump hw_params when $LIBASOUND_DEBUG is set to >= 1
27d5ac70f0Sopenharmony_ci */
28d5ac70f0Sopenharmony_cistatic void dump_hw_params(snd_pcm_hw_params_t *params, const char *type,
29d5ac70f0Sopenharmony_ci			   snd_pcm_hw_param_t var, unsigned int val, int err)
30d5ac70f0Sopenharmony_ci{
31d5ac70f0Sopenharmony_ci	const char *verbose = getenv("LIBASOUND_DEBUG");
32d5ac70f0Sopenharmony_ci	snd_output_t *out;
33d5ac70f0Sopenharmony_ci
34d5ac70f0Sopenharmony_ci	if (! verbose || ! *verbose || atoi(verbose) < 1)
35d5ac70f0Sopenharmony_ci		return;
36d5ac70f0Sopenharmony_ci	if (snd_output_stdio_attach(&out, stderr, 0) < 0)
37d5ac70f0Sopenharmony_ci		return;
38d5ac70f0Sopenharmony_ci	fprintf(stderr, "ALSA ERROR hw_params: %s (%s)\n",
39d5ac70f0Sopenharmony_ci		type, snd_pcm_hw_param_name(var));
40d5ac70f0Sopenharmony_ci	fprintf(stderr, "           value = ");
41d5ac70f0Sopenharmony_ci	switch (var) {
42d5ac70f0Sopenharmony_ci	case SND_PCM_HW_PARAM_ACCESS:
43d5ac70f0Sopenharmony_ci		fprintf(stderr, "%s", snd_pcm_access_name(val));
44d5ac70f0Sopenharmony_ci		break;
45d5ac70f0Sopenharmony_ci	case SND_PCM_HW_PARAM_FORMAT:
46d5ac70f0Sopenharmony_ci		fprintf(stderr, "%s", snd_pcm_format_name(val));
47d5ac70f0Sopenharmony_ci		break;
48d5ac70f0Sopenharmony_ci	case SND_PCM_HW_PARAM_SUBFORMAT:
49d5ac70f0Sopenharmony_ci		fprintf(stderr, "%s", snd_pcm_subformat_name(val));
50d5ac70f0Sopenharmony_ci		break;
51d5ac70f0Sopenharmony_ci	default:
52d5ac70f0Sopenharmony_ci		fprintf(stderr, "%u", val);
53d5ac70f0Sopenharmony_ci	}
54d5ac70f0Sopenharmony_ci	fprintf(stderr, " : %s\n", snd_strerror(err));
55d5ac70f0Sopenharmony_ci	snd_pcm_hw_params_dump(params, out);
56d5ac70f0Sopenharmony_ci	snd_output_close(out);
57d5ac70f0Sopenharmony_ci}
58d5ac70f0Sopenharmony_ci#else
59d5ac70f0Sopenharmony_cistatic inline void dump_hw_params(snd_pcm_hw_params_t *params, const char *type,
60d5ac70f0Sopenharmony_ci				  snd_pcm_hw_param_t var, unsigned int val, int err)
61d5ac70f0Sopenharmony_ci{
62d5ac70f0Sopenharmony_ci}
63d5ac70f0Sopenharmony_ci#endif
64d5ac70f0Sopenharmony_ci
65d5ac70f0Sopenharmony_cistatic inline int hw_is_mask(snd_pcm_hw_param_t var)
66d5ac70f0Sopenharmony_ci{
67d5ac70f0Sopenharmony_ci#if SND_PCM_HW_PARAM_FIRST_MASK == 0
68d5ac70f0Sopenharmony_ci	return var <= SND_PCM_HW_PARAM_LAST_MASK;
69d5ac70f0Sopenharmony_ci#else
70d5ac70f0Sopenharmony_ci	return var >= SND_PCM_HW_PARAM_FIRST_MASK &&
71d5ac70f0Sopenharmony_ci		var <= SND_PCM_HW_PARAM_LAST_MASK;
72d5ac70f0Sopenharmony_ci#endif
73d5ac70f0Sopenharmony_ci}
74d5ac70f0Sopenharmony_ci
75d5ac70f0Sopenharmony_cistatic inline int hw_is_interval(snd_pcm_hw_param_t var)
76d5ac70f0Sopenharmony_ci{
77d5ac70f0Sopenharmony_ci	return var >= SND_PCM_HW_PARAM_FIRST_INTERVAL &&
78d5ac70f0Sopenharmony_ci		var <= SND_PCM_HW_PARAM_LAST_INTERVAL;
79d5ac70f0Sopenharmony_ci}
80d5ac70f0Sopenharmony_ci
81d5ac70f0Sopenharmony_ci#define hw_param_mask(params,var) \
82d5ac70f0Sopenharmony_ci	&((params)->masks[(var) - SND_PCM_HW_PARAM_FIRST_MASK])
83d5ac70f0Sopenharmony_ci
84d5ac70f0Sopenharmony_ci#define hw_param_interval(params,var) \
85d5ac70f0Sopenharmony_ci	&((params)->intervals[(var) - SND_PCM_HW_PARAM_FIRST_INTERVAL])
86d5ac70f0Sopenharmony_ci
87d5ac70f0Sopenharmony_ci#define hw_param_mask_c hw_param_mask
88d5ac70f0Sopenharmony_ci#define hw_param_interval_c hw_param_interval
89d5ac70f0Sopenharmony_ci
90d5ac70f0Sopenharmony_cistatic void _snd_pcm_hw_param_any(snd_pcm_hw_params_t *params, snd_pcm_hw_param_t var)
91d5ac70f0Sopenharmony_ci{
92d5ac70f0Sopenharmony_ci	if (hw_is_mask(var)) {
93d5ac70f0Sopenharmony_ci		snd_mask_any(hw_param_mask(params, var));
94d5ac70f0Sopenharmony_ci		params->cmask |= 1 << var;
95d5ac70f0Sopenharmony_ci		params->rmask |= 1 << var;
96d5ac70f0Sopenharmony_ci		return;
97d5ac70f0Sopenharmony_ci	}
98d5ac70f0Sopenharmony_ci	if (hw_is_interval(var)) {
99d5ac70f0Sopenharmony_ci		snd_interval_any(hw_param_interval(params, var));
100d5ac70f0Sopenharmony_ci		params->cmask |= 1 << var;
101d5ac70f0Sopenharmony_ci		params->rmask |= 1 << var;
102d5ac70f0Sopenharmony_ci		return;
103d5ac70f0Sopenharmony_ci	}
104d5ac70f0Sopenharmony_ci	assert(0);
105d5ac70f0Sopenharmony_ci}
106d5ac70f0Sopenharmony_ci
107d5ac70f0Sopenharmony_ciint snd_pcm_hw_param_any(snd_pcm_t *pcm, snd_pcm_hw_params_t *params,
108d5ac70f0Sopenharmony_ci			 snd_pcm_hw_param_t var)
109d5ac70f0Sopenharmony_ci{
110d5ac70f0Sopenharmony_ci	_snd_pcm_hw_param_any(params, var);
111d5ac70f0Sopenharmony_ci	return snd_pcm_hw_refine(pcm, params);
112d5ac70f0Sopenharmony_ci}
113d5ac70f0Sopenharmony_ci
114d5ac70f0Sopenharmony_civoid _snd_pcm_hw_params_any(snd_pcm_hw_params_t *params)
115d5ac70f0Sopenharmony_ci{
116d5ac70f0Sopenharmony_ci	unsigned int k;
117d5ac70f0Sopenharmony_ci	memset(params, 0, sizeof(*params));
118d5ac70f0Sopenharmony_ci	for (k = SND_PCM_HW_PARAM_FIRST_MASK; k <= SND_PCM_HW_PARAM_LAST_MASK; k++)
119d5ac70f0Sopenharmony_ci		_snd_pcm_hw_param_any(params, k);
120d5ac70f0Sopenharmony_ci	for (k = SND_PCM_HW_PARAM_FIRST_INTERVAL; k <= SND_PCM_HW_PARAM_LAST_INTERVAL; k++)
121d5ac70f0Sopenharmony_ci		_snd_pcm_hw_param_any(params, k);
122d5ac70f0Sopenharmony_ci	params->rmask = ~0U;
123d5ac70f0Sopenharmony_ci	params->cmask = 0;
124d5ac70f0Sopenharmony_ci	params->info = ~0U;
125d5ac70f0Sopenharmony_ci}
126d5ac70f0Sopenharmony_ci
127d5ac70f0Sopenharmony_ci/* Return the value for field PAR if it's fixed in configuration space
128d5ac70f0Sopenharmony_ci   defined by PARAMS. Return -EINVAL otherwise
129d5ac70f0Sopenharmony_ci*/
130d5ac70f0Sopenharmony_ciint snd_pcm_hw_param_get(const snd_pcm_hw_params_t *params, snd_pcm_hw_param_t var,
131d5ac70f0Sopenharmony_ci			 unsigned int *val, int *dir)
132d5ac70f0Sopenharmony_ci{
133d5ac70f0Sopenharmony_ci	if (hw_is_mask(var)) {
134d5ac70f0Sopenharmony_ci		const snd_mask_t *mask = hw_param_mask_c(params, var);
135d5ac70f0Sopenharmony_ci		if (snd_mask_empty(mask) || !snd_mask_single(mask))
136d5ac70f0Sopenharmony_ci			return -EINVAL;
137d5ac70f0Sopenharmony_ci		if (dir)
138d5ac70f0Sopenharmony_ci			*dir = 0;
139d5ac70f0Sopenharmony_ci		if (val)
140d5ac70f0Sopenharmony_ci			*val = snd_mask_value(mask);
141d5ac70f0Sopenharmony_ci		return 0;
142d5ac70f0Sopenharmony_ci	} else if (hw_is_interval(var)) {
143d5ac70f0Sopenharmony_ci		const snd_interval_t *i = hw_param_interval_c(params, var);
144d5ac70f0Sopenharmony_ci		if (snd_interval_empty(i) || !snd_interval_single(i))
145d5ac70f0Sopenharmony_ci			return -EINVAL;
146d5ac70f0Sopenharmony_ci		if (dir)
147d5ac70f0Sopenharmony_ci			*dir = i->openmin;
148d5ac70f0Sopenharmony_ci		if (val)
149d5ac70f0Sopenharmony_ci			*val = snd_interval_value(i);
150d5ac70f0Sopenharmony_ci		return 0;
151d5ac70f0Sopenharmony_ci	}
152d5ac70f0Sopenharmony_ci	assert(0);
153d5ac70f0Sopenharmony_ci	return -EINVAL;
154d5ac70f0Sopenharmony_ci}
155d5ac70f0Sopenharmony_ci
156d5ac70f0Sopenharmony_ci/* Return the minimum value for field PAR. */
157d5ac70f0Sopenharmony_ciint snd_pcm_hw_param_get_min(const snd_pcm_hw_params_t *params, snd_pcm_hw_param_t var,
158d5ac70f0Sopenharmony_ci			     unsigned int *val, int *dir)
159d5ac70f0Sopenharmony_ci{
160d5ac70f0Sopenharmony_ci	if (hw_is_mask(var)) {
161d5ac70f0Sopenharmony_ci		const snd_mask_t *m = hw_param_mask_c(params, var);
162d5ac70f0Sopenharmony_ci		assert(!snd_mask_empty(m));
163d5ac70f0Sopenharmony_ci		if (dir)
164d5ac70f0Sopenharmony_ci			*dir = 0;
165d5ac70f0Sopenharmony_ci		if (val)
166d5ac70f0Sopenharmony_ci			*val = snd_mask_min(m);
167d5ac70f0Sopenharmony_ci		return 0;
168d5ac70f0Sopenharmony_ci	} else if (hw_is_interval(var)) {
169d5ac70f0Sopenharmony_ci		const snd_interval_t *i = hw_param_interval_c(params, var);
170d5ac70f0Sopenharmony_ci		assert(!snd_interval_empty(i));
171d5ac70f0Sopenharmony_ci		if (dir)
172d5ac70f0Sopenharmony_ci			*dir = i->openmin;
173d5ac70f0Sopenharmony_ci		if (val)
174d5ac70f0Sopenharmony_ci			*val = snd_interval_min(i);
175d5ac70f0Sopenharmony_ci		return 0;
176d5ac70f0Sopenharmony_ci	}
177d5ac70f0Sopenharmony_ci	assert(0);
178d5ac70f0Sopenharmony_ci	return 0;
179d5ac70f0Sopenharmony_ci}
180d5ac70f0Sopenharmony_ci
181d5ac70f0Sopenharmony_ci/* Return the maximum value for field PAR. */
182d5ac70f0Sopenharmony_ciint snd_pcm_hw_param_get_max(const snd_pcm_hw_params_t *params, snd_pcm_hw_param_t var,
183d5ac70f0Sopenharmony_ci			     unsigned int *val, int *dir)
184d5ac70f0Sopenharmony_ci{
185d5ac70f0Sopenharmony_ci	if (hw_is_mask(var)) {
186d5ac70f0Sopenharmony_ci		const snd_mask_t *m = hw_param_mask_c(params, var);
187d5ac70f0Sopenharmony_ci		assert(!snd_mask_empty(m));
188d5ac70f0Sopenharmony_ci		if (dir)
189d5ac70f0Sopenharmony_ci			*dir = 0;
190d5ac70f0Sopenharmony_ci		if (val)
191d5ac70f0Sopenharmony_ci			*val = snd_mask_max(m);
192d5ac70f0Sopenharmony_ci		return 0;
193d5ac70f0Sopenharmony_ci	} else if (hw_is_interval(var)) {
194d5ac70f0Sopenharmony_ci		const snd_interval_t *i = hw_param_interval_c(params, var);
195d5ac70f0Sopenharmony_ci		assert(!snd_interval_empty(i));
196d5ac70f0Sopenharmony_ci		if (dir)
197d5ac70f0Sopenharmony_ci			*dir = - (int) i->openmax;
198d5ac70f0Sopenharmony_ci		if (val)
199d5ac70f0Sopenharmony_ci			*val = snd_interval_max(i);
200d5ac70f0Sopenharmony_ci		return 0;
201d5ac70f0Sopenharmony_ci	}
202d5ac70f0Sopenharmony_ci	assert(0);
203d5ac70f0Sopenharmony_ci	return 0;
204d5ac70f0Sopenharmony_ci}
205d5ac70f0Sopenharmony_ci
206d5ac70f0Sopenharmony_ci/* Return the mask for field PAR.
207d5ac70f0Sopenharmony_ci   This function can be called only for SND_PCM_HW_PARAM_ACCESS,
208d5ac70f0Sopenharmony_ci   SND_PCM_HW_PARAM_FORMAT, SND_PCM_HW_PARAM_SUBFORMAT. */
209d5ac70f0Sopenharmony_ciconst snd_mask_t *snd_pcm_hw_param_get_mask(const snd_pcm_hw_params_t *params,
210d5ac70f0Sopenharmony_ci					   snd_pcm_hw_param_t var)
211d5ac70f0Sopenharmony_ci{
212d5ac70f0Sopenharmony_ci	assert(hw_is_mask(var));
213d5ac70f0Sopenharmony_ci	return hw_param_mask_c(params, var);
214d5ac70f0Sopenharmony_ci}
215d5ac70f0Sopenharmony_ci
216d5ac70f0Sopenharmony_ci/* Return the interval for field PAR.
217d5ac70f0Sopenharmony_ci   This function cannot be called for SND_PCM_HW_PARAM_ACCESS,
218d5ac70f0Sopenharmony_ci   SND_PCM_HW_PARAM_FORMAT, SND_PCM_HW_PARAM_SUBFORMAT. */
219d5ac70f0Sopenharmony_ciconst snd_interval_t *snd_pcm_hw_param_get_interval(const snd_pcm_hw_params_t *params,
220d5ac70f0Sopenharmony_ci						  snd_pcm_hw_param_t var)
221d5ac70f0Sopenharmony_ci{
222d5ac70f0Sopenharmony_ci	assert(hw_is_interval(var));
223d5ac70f0Sopenharmony_ci	return hw_param_interval_c(params, var);
224d5ac70f0Sopenharmony_ci}
225d5ac70f0Sopenharmony_ci
226d5ac70f0Sopenharmony_ci/* --- Refinement functions --- */
227d5ac70f0Sopenharmony_ci
228d5ac70f0Sopenharmony_ciint _snd_pcm_hw_param_set_interval(snd_pcm_hw_params_t *params,
229d5ac70f0Sopenharmony_ci				   snd_pcm_hw_param_t var,
230d5ac70f0Sopenharmony_ci				   const snd_interval_t *val)
231d5ac70f0Sopenharmony_ci{
232d5ac70f0Sopenharmony_ci	int changed;
233d5ac70f0Sopenharmony_ci	assert(hw_is_interval(var));
234d5ac70f0Sopenharmony_ci	changed = snd_interval_refine(hw_param_interval(params, var), val);
235d5ac70f0Sopenharmony_ci	if (changed) {
236d5ac70f0Sopenharmony_ci		params->cmask |= 1 << var;
237d5ac70f0Sopenharmony_ci		params->rmask |= 1 << var;
238d5ac70f0Sopenharmony_ci	}
239d5ac70f0Sopenharmony_ci	return changed;
240d5ac70f0Sopenharmony_ci}
241d5ac70f0Sopenharmony_ci
242d5ac70f0Sopenharmony_civoid _snd_pcm_hw_param_set_empty(snd_pcm_hw_params_t *params,
243d5ac70f0Sopenharmony_ci				 snd_pcm_hw_param_t var)
244d5ac70f0Sopenharmony_ci{
245d5ac70f0Sopenharmony_ci	if (hw_is_mask(var)) {
246d5ac70f0Sopenharmony_ci		snd_mask_none(hw_param_mask(params, var));
247d5ac70f0Sopenharmony_ci		params->cmask |= 1 << var;
248d5ac70f0Sopenharmony_ci		params->rmask |= 1 << var;
249d5ac70f0Sopenharmony_ci	} else if (hw_is_interval(var)) {
250d5ac70f0Sopenharmony_ci		snd_interval_none(hw_param_interval(params, var));
251d5ac70f0Sopenharmony_ci		params->cmask |= 1 << var;
252d5ac70f0Sopenharmony_ci		params->rmask |= 1 << var;
253d5ac70f0Sopenharmony_ci	} else {
254d5ac70f0Sopenharmony_ci		assert(0);
255d5ac70f0Sopenharmony_ci	}
256d5ac70f0Sopenharmony_ci}
257d5ac70f0Sopenharmony_ci
258d5ac70f0Sopenharmony_cistatic int _snd_pcm_hw_param_set_integer(snd_pcm_hw_params_t *params,
259d5ac70f0Sopenharmony_ci					 snd_pcm_hw_param_t var)
260d5ac70f0Sopenharmony_ci{
261d5ac70f0Sopenharmony_ci	int changed;
262d5ac70f0Sopenharmony_ci	assert(hw_is_interval(var));
263d5ac70f0Sopenharmony_ci	changed = snd_interval_setinteger(hw_param_interval(params, var));
264d5ac70f0Sopenharmony_ci	if (changed) {
265d5ac70f0Sopenharmony_ci		params->cmask |= 1 << var;
266d5ac70f0Sopenharmony_ci		params->rmask |= 1 << var;
267d5ac70f0Sopenharmony_ci	}
268d5ac70f0Sopenharmony_ci	return changed;
269d5ac70f0Sopenharmony_ci}
270d5ac70f0Sopenharmony_ci
271d5ac70f0Sopenharmony_ci/* Inside configuration space defined by PARAMS remove from PAR all
272d5ac70f0Sopenharmony_ci   non integer values. Reduce configuration space accordingly.
273d5ac70f0Sopenharmony_ci   Return -EINVAL if the configuration space is empty
274d5ac70f0Sopenharmony_ci*/
275d5ac70f0Sopenharmony_ciint snd_pcm_hw_param_set_integer(snd_pcm_t *pcm,
276d5ac70f0Sopenharmony_ci				 snd_pcm_hw_params_t *params,
277d5ac70f0Sopenharmony_ci				 snd_set_mode_t mode,
278d5ac70f0Sopenharmony_ci				 snd_pcm_hw_param_t var)
279d5ac70f0Sopenharmony_ci{
280d5ac70f0Sopenharmony_ci	snd_pcm_hw_params_t save;
281d5ac70f0Sopenharmony_ci	int err;
282d5ac70f0Sopenharmony_ci	switch (mode) {
283d5ac70f0Sopenharmony_ci	case SND_CHANGE:
284d5ac70f0Sopenharmony_ci		break;
285d5ac70f0Sopenharmony_ci	case SND_TRY:
286d5ac70f0Sopenharmony_ci		save = *params;
287d5ac70f0Sopenharmony_ci		break;
288d5ac70f0Sopenharmony_ci	case SND_TEST:
289d5ac70f0Sopenharmony_ci		save = *params;
290d5ac70f0Sopenharmony_ci		params = &save;
291d5ac70f0Sopenharmony_ci		break;
292d5ac70f0Sopenharmony_ci	default:
293d5ac70f0Sopenharmony_ci		assert(0);
294d5ac70f0Sopenharmony_ci		return -EINVAL;
295d5ac70f0Sopenharmony_ci	}
296d5ac70f0Sopenharmony_ci	err = _snd_pcm_hw_param_set_integer(params, var);
297d5ac70f0Sopenharmony_ci	if (err < 0)
298d5ac70f0Sopenharmony_ci		goto _fail;
299d5ac70f0Sopenharmony_ci	if (params->rmask) {
300d5ac70f0Sopenharmony_ci		err = snd_pcm_hw_refine(pcm, params);
301d5ac70f0Sopenharmony_ci		if (err < 0)
302d5ac70f0Sopenharmony_ci			goto _fail;
303d5ac70f0Sopenharmony_ci	}
304d5ac70f0Sopenharmony_ci	return 0;
305d5ac70f0Sopenharmony_ci _fail:
306d5ac70f0Sopenharmony_ci	if (mode == SND_TRY)
307d5ac70f0Sopenharmony_ci		*params = save;
308d5ac70f0Sopenharmony_ci	return err;
309d5ac70f0Sopenharmony_ci}
310d5ac70f0Sopenharmony_ci
311d5ac70f0Sopenharmony_cistatic int _snd_pcm_hw_param_set_first(snd_pcm_hw_params_t *params,
312d5ac70f0Sopenharmony_ci				       snd_pcm_hw_param_t var)
313d5ac70f0Sopenharmony_ci{
314d5ac70f0Sopenharmony_ci	int changed;
315d5ac70f0Sopenharmony_ci	if (hw_is_mask(var))
316d5ac70f0Sopenharmony_ci		changed = snd_mask_refine_first(hw_param_mask(params, var));
317d5ac70f0Sopenharmony_ci	else if (hw_is_interval(var))
318d5ac70f0Sopenharmony_ci		changed = snd_interval_refine_first(hw_param_interval(params, var));
319d5ac70f0Sopenharmony_ci	else {
320d5ac70f0Sopenharmony_ci		assert(0);
321d5ac70f0Sopenharmony_ci		return -EINVAL;
322d5ac70f0Sopenharmony_ci	}
323d5ac70f0Sopenharmony_ci	if (changed > 0) {
324d5ac70f0Sopenharmony_ci		params->cmask |= 1 << var;
325d5ac70f0Sopenharmony_ci		params->rmask |= 1 << var;
326d5ac70f0Sopenharmony_ci	}
327d5ac70f0Sopenharmony_ci	return changed;
328d5ac70f0Sopenharmony_ci}
329d5ac70f0Sopenharmony_ci
330d5ac70f0Sopenharmony_ci
331d5ac70f0Sopenharmony_ci/* Inside configuration space defined by PARAMS remove from PAR all
332d5ac70f0Sopenharmony_ci   values > minimum. Reduce configuration space accordingly.
333d5ac70f0Sopenharmony_ci   Return the minimum.
334d5ac70f0Sopenharmony_ci*/
335d5ac70f0Sopenharmony_ciint snd_pcm_hw_param_set_first(snd_pcm_t *pcm,
336d5ac70f0Sopenharmony_ci			       snd_pcm_hw_params_t *params,
337d5ac70f0Sopenharmony_ci			       snd_pcm_hw_param_t var,
338d5ac70f0Sopenharmony_ci			       unsigned int *rval, int *dir)
339d5ac70f0Sopenharmony_ci{
340d5ac70f0Sopenharmony_ci	int err;
341d5ac70f0Sopenharmony_ci
342d5ac70f0Sopenharmony_ci	err = _snd_pcm_hw_param_set_first(params, var);
343d5ac70f0Sopenharmony_ci	if (err < 0)
344d5ac70f0Sopenharmony_ci		return err;
345d5ac70f0Sopenharmony_ci	if (params->rmask) {
346d5ac70f0Sopenharmony_ci		err = snd_pcm_hw_refine(pcm, params);
347d5ac70f0Sopenharmony_ci		if (err < 0)
348d5ac70f0Sopenharmony_ci			return err;
349d5ac70f0Sopenharmony_ci	}
350d5ac70f0Sopenharmony_ci	return snd_pcm_hw_param_get(params, var, rval, dir);
351d5ac70f0Sopenharmony_ci}
352d5ac70f0Sopenharmony_ci
353d5ac70f0Sopenharmony_cistatic int _snd_pcm_hw_param_set_last(snd_pcm_hw_params_t *params,
354d5ac70f0Sopenharmony_ci				      snd_pcm_hw_param_t var)
355d5ac70f0Sopenharmony_ci{
356d5ac70f0Sopenharmony_ci	int changed;
357d5ac70f0Sopenharmony_ci	if (hw_is_mask(var))
358d5ac70f0Sopenharmony_ci		changed = snd_mask_refine_last(hw_param_mask(params, var));
359d5ac70f0Sopenharmony_ci	else if (hw_is_interval(var))
360d5ac70f0Sopenharmony_ci		changed = snd_interval_refine_last(hw_param_interval(params, var));
361d5ac70f0Sopenharmony_ci	else {
362d5ac70f0Sopenharmony_ci		assert(0);
363d5ac70f0Sopenharmony_ci		return -EINVAL;
364d5ac70f0Sopenharmony_ci	}
365d5ac70f0Sopenharmony_ci	if (changed > 0) {
366d5ac70f0Sopenharmony_ci		params->cmask |= 1 << var;
367d5ac70f0Sopenharmony_ci		params->rmask |= 1 << var;
368d5ac70f0Sopenharmony_ci	}
369d5ac70f0Sopenharmony_ci	return changed;
370d5ac70f0Sopenharmony_ci}
371d5ac70f0Sopenharmony_ci
372d5ac70f0Sopenharmony_ci
373d5ac70f0Sopenharmony_ci/* Inside configuration space defined by PARAMS remove from PAR all
374d5ac70f0Sopenharmony_ci   values < maximum. Reduce configuration space accordingly.
375d5ac70f0Sopenharmony_ci   Return the maximum.
376d5ac70f0Sopenharmony_ci*/
377d5ac70f0Sopenharmony_ciint snd_pcm_hw_param_set_last(snd_pcm_t *pcm,
378d5ac70f0Sopenharmony_ci			      snd_pcm_hw_params_t *params,
379d5ac70f0Sopenharmony_ci			      snd_pcm_hw_param_t var,
380d5ac70f0Sopenharmony_ci			      unsigned int *rval, int *dir)
381d5ac70f0Sopenharmony_ci{
382d5ac70f0Sopenharmony_ci	int err;
383d5ac70f0Sopenharmony_ci
384d5ac70f0Sopenharmony_ci	err = _snd_pcm_hw_param_set_last(params, var);
385d5ac70f0Sopenharmony_ci	if (err < 0)
386d5ac70f0Sopenharmony_ci		return err;
387d5ac70f0Sopenharmony_ci	if (params->rmask) {
388d5ac70f0Sopenharmony_ci		err = snd_pcm_hw_refine(pcm, params);
389d5ac70f0Sopenharmony_ci		if (err < 0)
390d5ac70f0Sopenharmony_ci			return err;
391d5ac70f0Sopenharmony_ci	}
392d5ac70f0Sopenharmony_ci	return snd_pcm_hw_param_get(params, var, rval, dir);
393d5ac70f0Sopenharmony_ci}
394d5ac70f0Sopenharmony_ci
395d5ac70f0Sopenharmony_ciint _snd_pcm_hw_param_set_min(snd_pcm_hw_params_t *params,
396d5ac70f0Sopenharmony_ci			      snd_pcm_hw_param_t var, unsigned int val, int dir)
397d5ac70f0Sopenharmony_ci{
398d5ac70f0Sopenharmony_ci	int changed;
399d5ac70f0Sopenharmony_ci	int openmin = 0;
400d5ac70f0Sopenharmony_ci	if (dir) {
401d5ac70f0Sopenharmony_ci		if (dir > 0) {
402d5ac70f0Sopenharmony_ci			openmin = 1;
403d5ac70f0Sopenharmony_ci		} else if (dir < 0) {
404d5ac70f0Sopenharmony_ci			if (val > 0) {
405d5ac70f0Sopenharmony_ci				openmin = 1;
406d5ac70f0Sopenharmony_ci				val--;
407d5ac70f0Sopenharmony_ci			}
408d5ac70f0Sopenharmony_ci		}
409d5ac70f0Sopenharmony_ci	}
410d5ac70f0Sopenharmony_ci	if (hw_is_mask(var))
411d5ac70f0Sopenharmony_ci		changed = snd_mask_refine_min(hw_param_mask(params, var), val + !!openmin);
412d5ac70f0Sopenharmony_ci	else if (hw_is_interval(var))
413d5ac70f0Sopenharmony_ci		changed = snd_interval_refine_min(hw_param_interval(params, var), val, openmin);
414d5ac70f0Sopenharmony_ci	else {
415d5ac70f0Sopenharmony_ci		assert(0);
416d5ac70f0Sopenharmony_ci		return -EINVAL;
417d5ac70f0Sopenharmony_ci	}
418d5ac70f0Sopenharmony_ci	if (changed) {
419d5ac70f0Sopenharmony_ci		params->cmask |= 1 << var;
420d5ac70f0Sopenharmony_ci		params->rmask |= 1 << var;
421d5ac70f0Sopenharmony_ci	}
422d5ac70f0Sopenharmony_ci	return changed;
423d5ac70f0Sopenharmony_ci}
424d5ac70f0Sopenharmony_ci
425d5ac70f0Sopenharmony_ci/* Inside configuration space defined by PARAMS remove from PAR all
426d5ac70f0Sopenharmony_ci   values < VAL. Reduce configuration space accordingly.
427d5ac70f0Sopenharmony_ci   Return new minimum or -EINVAL if the configuration space is empty
428d5ac70f0Sopenharmony_ci*/
429d5ac70f0Sopenharmony_ciint snd_pcm_hw_param_set_min(snd_pcm_t *pcm, snd_pcm_hw_params_t *params,
430d5ac70f0Sopenharmony_ci			     snd_set_mode_t mode,
431d5ac70f0Sopenharmony_ci			     snd_pcm_hw_param_t var, unsigned int *val, int *dir)
432d5ac70f0Sopenharmony_ci{
433d5ac70f0Sopenharmony_ci	snd_pcm_hw_params_t save;
434d5ac70f0Sopenharmony_ci	int err;
435d5ac70f0Sopenharmony_ci	switch (mode) {
436d5ac70f0Sopenharmony_ci	case SND_CHANGE:
437d5ac70f0Sopenharmony_ci		break;
438d5ac70f0Sopenharmony_ci	case SND_TRY:
439d5ac70f0Sopenharmony_ci		save = *params;
440d5ac70f0Sopenharmony_ci		break;
441d5ac70f0Sopenharmony_ci	case SND_TEST:
442d5ac70f0Sopenharmony_ci		save = *params;
443d5ac70f0Sopenharmony_ci		params = &save;
444d5ac70f0Sopenharmony_ci		break;
445d5ac70f0Sopenharmony_ci	default:
446d5ac70f0Sopenharmony_ci		assert(0);
447d5ac70f0Sopenharmony_ci		return -EINVAL;
448d5ac70f0Sopenharmony_ci	}
449d5ac70f0Sopenharmony_ci	err = _snd_pcm_hw_param_set_min(params, var, *val, dir ? *dir : 0);
450d5ac70f0Sopenharmony_ci	if (err < 0)
451d5ac70f0Sopenharmony_ci		goto _fail;
452d5ac70f0Sopenharmony_ci	if ((mode != SND_TEST || hw_is_interval(var)) && params->rmask) {
453d5ac70f0Sopenharmony_ci		err = snd_pcm_hw_refine(pcm, params);
454d5ac70f0Sopenharmony_ci		if (err < 0)
455d5ac70f0Sopenharmony_ci			goto _fail;
456d5ac70f0Sopenharmony_ci		if (snd_pcm_hw_param_empty(params, var)) {
457d5ac70f0Sopenharmony_ci			err = -ENOENT;
458d5ac70f0Sopenharmony_ci			goto _fail;
459d5ac70f0Sopenharmony_ci		}
460d5ac70f0Sopenharmony_ci	}
461d5ac70f0Sopenharmony_ci	return snd_pcm_hw_param_get_min(params, var, val, dir);
462d5ac70f0Sopenharmony_ci _fail:
463d5ac70f0Sopenharmony_ci	if (mode == SND_TRY)
464d5ac70f0Sopenharmony_ci		*params = save;
465d5ac70f0Sopenharmony_ci	if (err < 0 && mode == SND_TRY)
466d5ac70f0Sopenharmony_ci		dump_hw_params(params, "set_min", var, *val, err);
467d5ac70f0Sopenharmony_ci	return err;
468d5ac70f0Sopenharmony_ci}
469d5ac70f0Sopenharmony_ci
470d5ac70f0Sopenharmony_ciint _snd_pcm_hw_param_set_max(snd_pcm_hw_params_t *params,
471d5ac70f0Sopenharmony_ci			      snd_pcm_hw_param_t var, unsigned int val, int dir)
472d5ac70f0Sopenharmony_ci{
473d5ac70f0Sopenharmony_ci	int changed;
474d5ac70f0Sopenharmony_ci	int openmax = 0;
475d5ac70f0Sopenharmony_ci	if (dir) {
476d5ac70f0Sopenharmony_ci		if (dir < 0) {
477d5ac70f0Sopenharmony_ci			openmax = 1;
478d5ac70f0Sopenharmony_ci		} else if (dir > 0) {
479d5ac70f0Sopenharmony_ci			openmax = 1;
480d5ac70f0Sopenharmony_ci			val++;
481d5ac70f0Sopenharmony_ci		}
482d5ac70f0Sopenharmony_ci	}
483d5ac70f0Sopenharmony_ci	if (hw_is_mask(var)) {
484d5ac70f0Sopenharmony_ci		if (val == 0 && openmax) {
485d5ac70f0Sopenharmony_ci		snd_mask_none(hw_param_mask(params, var));
486d5ac70f0Sopenharmony_ci			changed = -EINVAL;
487d5ac70f0Sopenharmony_ci		} else
488d5ac70f0Sopenharmony_ci			changed = snd_mask_refine_max(hw_param_mask(params, var), val - !!openmax);
489d5ac70f0Sopenharmony_ci	} else if (hw_is_interval(var))
490d5ac70f0Sopenharmony_ci		changed = snd_interval_refine_max(hw_param_interval(params, var), val, openmax);
491d5ac70f0Sopenharmony_ci	else {
492d5ac70f0Sopenharmony_ci		assert(0);
493d5ac70f0Sopenharmony_ci		return -EINVAL;
494d5ac70f0Sopenharmony_ci	}
495d5ac70f0Sopenharmony_ci	if (changed) {
496d5ac70f0Sopenharmony_ci		params->cmask |= 1 << var;
497d5ac70f0Sopenharmony_ci		params->rmask |= 1 << var;
498d5ac70f0Sopenharmony_ci	}
499d5ac70f0Sopenharmony_ci	return changed;
500d5ac70f0Sopenharmony_ci}
501d5ac70f0Sopenharmony_ci
502d5ac70f0Sopenharmony_ci/* Inside configuration space defined by PARAMS remove from PAR all
503d5ac70f0Sopenharmony_ci   values >= VAL + 1. Reduce configuration space accordingly.
504d5ac70f0Sopenharmony_ci   Return new maximum or -EINVAL if the configuration space is empty
505d5ac70f0Sopenharmony_ci*/
506d5ac70f0Sopenharmony_ciint snd_pcm_hw_param_set_max(snd_pcm_t *pcm, snd_pcm_hw_params_t *params,
507d5ac70f0Sopenharmony_ci			     snd_set_mode_t mode,
508d5ac70f0Sopenharmony_ci			     snd_pcm_hw_param_t var, unsigned int *val, int *dir)
509d5ac70f0Sopenharmony_ci{
510d5ac70f0Sopenharmony_ci	snd_pcm_hw_params_t save;
511d5ac70f0Sopenharmony_ci	int err;
512d5ac70f0Sopenharmony_ci	switch (mode) {
513d5ac70f0Sopenharmony_ci	case SND_CHANGE:
514d5ac70f0Sopenharmony_ci		break;
515d5ac70f0Sopenharmony_ci	case SND_TRY:
516d5ac70f0Sopenharmony_ci		save = *params;
517d5ac70f0Sopenharmony_ci		break;
518d5ac70f0Sopenharmony_ci	case SND_TEST:
519d5ac70f0Sopenharmony_ci		save = *params;
520d5ac70f0Sopenharmony_ci		params = &save;
521d5ac70f0Sopenharmony_ci		break;
522d5ac70f0Sopenharmony_ci	default:
523d5ac70f0Sopenharmony_ci		assert(0);
524d5ac70f0Sopenharmony_ci		return -EINVAL;
525d5ac70f0Sopenharmony_ci	}
526d5ac70f0Sopenharmony_ci	err = _snd_pcm_hw_param_set_max(params, var, *val, dir ? *dir : 0);
527d5ac70f0Sopenharmony_ci	if (err < 0)
528d5ac70f0Sopenharmony_ci		goto _fail;
529d5ac70f0Sopenharmony_ci	if ((mode != SND_TEST || hw_is_interval(var)) && params->rmask) {
530d5ac70f0Sopenharmony_ci		err = snd_pcm_hw_refine(pcm, params);
531d5ac70f0Sopenharmony_ci		if (err < 0)
532d5ac70f0Sopenharmony_ci			goto _fail;
533d5ac70f0Sopenharmony_ci		if (snd_pcm_hw_param_empty(params, var)) {
534d5ac70f0Sopenharmony_ci			err = -ENOENT;
535d5ac70f0Sopenharmony_ci			goto _fail;
536d5ac70f0Sopenharmony_ci		}
537d5ac70f0Sopenharmony_ci	}
538d5ac70f0Sopenharmony_ci	return snd_pcm_hw_param_get_max(params, var, val, dir);
539d5ac70f0Sopenharmony_ci _fail:
540d5ac70f0Sopenharmony_ci	if (mode == SND_TRY)
541d5ac70f0Sopenharmony_ci		*params = save;
542d5ac70f0Sopenharmony_ci	if (err < 0 && mode == SND_TRY)
543d5ac70f0Sopenharmony_ci		dump_hw_params(params, "set_max", var, *val, err);
544d5ac70f0Sopenharmony_ci	return err;
545d5ac70f0Sopenharmony_ci}
546d5ac70f0Sopenharmony_ci
547d5ac70f0Sopenharmony_ciint _snd_pcm_hw_param_set_minmax(snd_pcm_hw_params_t *params,
548d5ac70f0Sopenharmony_ci				 snd_pcm_hw_param_t var,
549d5ac70f0Sopenharmony_ci				 unsigned int min, int mindir,
550d5ac70f0Sopenharmony_ci				 unsigned int max, int maxdir)
551d5ac70f0Sopenharmony_ci{
552d5ac70f0Sopenharmony_ci	int changed, c1, c2;
553d5ac70f0Sopenharmony_ci	int openmin = 0, openmax = 0;
554d5ac70f0Sopenharmony_ci	if (mindir) {
555d5ac70f0Sopenharmony_ci		if (mindir > 0) {
556d5ac70f0Sopenharmony_ci			openmin = 1;
557d5ac70f0Sopenharmony_ci		} else if (mindir < 0) {
558d5ac70f0Sopenharmony_ci			if (min > 0) {
559d5ac70f0Sopenharmony_ci				openmin = 1;
560d5ac70f0Sopenharmony_ci				min--;
561d5ac70f0Sopenharmony_ci			}
562d5ac70f0Sopenharmony_ci		}
563d5ac70f0Sopenharmony_ci	}
564d5ac70f0Sopenharmony_ci	if (maxdir) {
565d5ac70f0Sopenharmony_ci		if (maxdir < 0) {
566d5ac70f0Sopenharmony_ci			openmax = 1;
567d5ac70f0Sopenharmony_ci		} else if (maxdir > 0) {
568d5ac70f0Sopenharmony_ci			openmax = 1;
569d5ac70f0Sopenharmony_ci			max++;
570d5ac70f0Sopenharmony_ci		}
571d5ac70f0Sopenharmony_ci	}
572d5ac70f0Sopenharmony_ci	if (hw_is_mask(var)) {
573d5ac70f0Sopenharmony_ci		snd_mask_t *mask = hw_param_mask(params, var);
574d5ac70f0Sopenharmony_ci		if (max == 0 && openmax) {
575d5ac70f0Sopenharmony_ci			snd_mask_none(mask);
576d5ac70f0Sopenharmony_ci			changed = -EINVAL;
577d5ac70f0Sopenharmony_ci		} else {
578d5ac70f0Sopenharmony_ci			c1 = snd_mask_refine_min(mask, min + !!openmin);
579d5ac70f0Sopenharmony_ci			if (c1 < 0)
580d5ac70f0Sopenharmony_ci				changed = c1;
581d5ac70f0Sopenharmony_ci			else {
582d5ac70f0Sopenharmony_ci				c2 = snd_mask_refine_max(mask, max - !!openmax);
583d5ac70f0Sopenharmony_ci				if (c2 < 0)
584d5ac70f0Sopenharmony_ci					changed = c2;
585d5ac70f0Sopenharmony_ci				else
586d5ac70f0Sopenharmony_ci					changed = (c1 || c2);
587d5ac70f0Sopenharmony_ci			}
588d5ac70f0Sopenharmony_ci		}
589d5ac70f0Sopenharmony_ci	}
590d5ac70f0Sopenharmony_ci	else if (hw_is_interval(var)) {
591d5ac70f0Sopenharmony_ci		snd_interval_t *i = hw_param_interval(params, var);
592d5ac70f0Sopenharmony_ci		c1 = snd_interval_refine_min(i, min, openmin);
593d5ac70f0Sopenharmony_ci		if (c1 < 0)
594d5ac70f0Sopenharmony_ci			changed = c1;
595d5ac70f0Sopenharmony_ci		else {
596d5ac70f0Sopenharmony_ci			c2 = snd_interval_refine_max(i, max, openmax);
597d5ac70f0Sopenharmony_ci			if (c2 < 0)
598d5ac70f0Sopenharmony_ci				changed = c2;
599d5ac70f0Sopenharmony_ci			else
600d5ac70f0Sopenharmony_ci				changed = (c1 || c2);
601d5ac70f0Sopenharmony_ci		}
602d5ac70f0Sopenharmony_ci	} else {
603d5ac70f0Sopenharmony_ci		assert(0);
604d5ac70f0Sopenharmony_ci		return -EINVAL;
605d5ac70f0Sopenharmony_ci	}
606d5ac70f0Sopenharmony_ci	if (changed) {
607d5ac70f0Sopenharmony_ci		params->cmask |= 1 << var;
608d5ac70f0Sopenharmony_ci		params->rmask |= 1 << var;
609d5ac70f0Sopenharmony_ci	}
610d5ac70f0Sopenharmony_ci	return changed;
611d5ac70f0Sopenharmony_ci}
612d5ac70f0Sopenharmony_ci
613d5ac70f0Sopenharmony_ci/* Inside configuration space defined by PARAMS remove from PAR all
614d5ac70f0Sopenharmony_ci   values < MIN and all values > MAX. Reduce configuration space accordingly.
615d5ac70f0Sopenharmony_ci   Return 0 or -EINVAL if the configuration space is empty
616d5ac70f0Sopenharmony_ci*/
617d5ac70f0Sopenharmony_ciint snd_pcm_hw_param_set_minmax(snd_pcm_t *pcm, snd_pcm_hw_params_t *params,
618d5ac70f0Sopenharmony_ci				snd_set_mode_t mode,
619d5ac70f0Sopenharmony_ci				snd_pcm_hw_param_t var,
620d5ac70f0Sopenharmony_ci				unsigned int *min, int *mindir,
621d5ac70f0Sopenharmony_ci				unsigned int *max, int *maxdir)
622d5ac70f0Sopenharmony_ci{
623d5ac70f0Sopenharmony_ci	snd_pcm_hw_params_t save;
624d5ac70f0Sopenharmony_ci	int err;
625d5ac70f0Sopenharmony_ci	switch (mode) {
626d5ac70f0Sopenharmony_ci	case SND_CHANGE:
627d5ac70f0Sopenharmony_ci		break;
628d5ac70f0Sopenharmony_ci	case SND_TRY:
629d5ac70f0Sopenharmony_ci		save = *params;
630d5ac70f0Sopenharmony_ci		break;
631d5ac70f0Sopenharmony_ci	case SND_TEST:
632d5ac70f0Sopenharmony_ci		save = *params;
633d5ac70f0Sopenharmony_ci		params = &save;
634d5ac70f0Sopenharmony_ci		break;
635d5ac70f0Sopenharmony_ci	default:
636d5ac70f0Sopenharmony_ci		assert(0);
637d5ac70f0Sopenharmony_ci		return -EINVAL;
638d5ac70f0Sopenharmony_ci	}
639d5ac70f0Sopenharmony_ci	err = _snd_pcm_hw_param_set_minmax(params, var,
640d5ac70f0Sopenharmony_ci					   *min, mindir ? *mindir : 0,
641d5ac70f0Sopenharmony_ci					   *max, maxdir ? *maxdir : 0);
642d5ac70f0Sopenharmony_ci	if (err < 0)
643d5ac70f0Sopenharmony_ci		goto _fail;
644d5ac70f0Sopenharmony_ci	if ((mode != SND_TEST || hw_is_interval(var)) && params->rmask) {
645d5ac70f0Sopenharmony_ci		err = snd_pcm_hw_refine(pcm, params);
646d5ac70f0Sopenharmony_ci		if (err < 0)
647d5ac70f0Sopenharmony_ci			goto _fail;
648d5ac70f0Sopenharmony_ci	}
649d5ac70f0Sopenharmony_ci	err = snd_pcm_hw_param_get_min(params, var, min, mindir);
650d5ac70f0Sopenharmony_ci	if (err < 0)
651d5ac70f0Sopenharmony_ci		return err;
652d5ac70f0Sopenharmony_ci	return snd_pcm_hw_param_get_max(params, var, max, maxdir);
653d5ac70f0Sopenharmony_ci _fail:
654d5ac70f0Sopenharmony_ci	if (mode == SND_TRY)
655d5ac70f0Sopenharmony_ci		*params = save;
656d5ac70f0Sopenharmony_ci	if (err < 0)
657d5ac70f0Sopenharmony_ci		dump_hw_params(params, "set_minmax", var, *min, err);
658d5ac70f0Sopenharmony_ci	return err;
659d5ac70f0Sopenharmony_ci}
660d5ac70f0Sopenharmony_ci
661d5ac70f0Sopenharmony_ciint _snd_pcm_hw_param_set(snd_pcm_hw_params_t *params,
662d5ac70f0Sopenharmony_ci			  snd_pcm_hw_param_t var, unsigned int val, int dir)
663d5ac70f0Sopenharmony_ci{
664d5ac70f0Sopenharmony_ci	int changed;
665d5ac70f0Sopenharmony_ci	if (hw_is_mask(var)) {
666d5ac70f0Sopenharmony_ci		snd_mask_t *m = hw_param_mask(params, var);
667d5ac70f0Sopenharmony_ci		if (val == 0 && dir < 0) {
668d5ac70f0Sopenharmony_ci			changed = -EINVAL;
669d5ac70f0Sopenharmony_ci			snd_mask_none(m);
670d5ac70f0Sopenharmony_ci		} else {
671d5ac70f0Sopenharmony_ci			if (dir > 0)
672d5ac70f0Sopenharmony_ci				val++;
673d5ac70f0Sopenharmony_ci			else if (dir < 0)
674d5ac70f0Sopenharmony_ci				val--;
675d5ac70f0Sopenharmony_ci			changed = snd_mask_refine_set(hw_param_mask(params, var), val);
676d5ac70f0Sopenharmony_ci		}
677d5ac70f0Sopenharmony_ci	} else if (hw_is_interval(var)) {
678d5ac70f0Sopenharmony_ci		snd_interval_t *i = hw_param_interval(params, var);
679d5ac70f0Sopenharmony_ci		if (val == 0 && dir < 0) {
680d5ac70f0Sopenharmony_ci			changed = -EINVAL;
681d5ac70f0Sopenharmony_ci			snd_interval_none(i);
682d5ac70f0Sopenharmony_ci		} else if (dir == 0)
683d5ac70f0Sopenharmony_ci			changed = snd_interval_refine_set(i, val);
684d5ac70f0Sopenharmony_ci		else {
685d5ac70f0Sopenharmony_ci			snd_interval_t t;
686d5ac70f0Sopenharmony_ci			t.openmin = 1;
687d5ac70f0Sopenharmony_ci			t.openmax = 1;
688d5ac70f0Sopenharmony_ci			t.empty = 0;
689d5ac70f0Sopenharmony_ci			t.integer = 0;
690d5ac70f0Sopenharmony_ci			if (dir < 0) {
691d5ac70f0Sopenharmony_ci				t.min = val - 1;
692d5ac70f0Sopenharmony_ci				t.max = val;
693d5ac70f0Sopenharmony_ci			} else {
694d5ac70f0Sopenharmony_ci				t.min = val;
695d5ac70f0Sopenharmony_ci				t.max = val+1;
696d5ac70f0Sopenharmony_ci			}
697d5ac70f0Sopenharmony_ci			changed = snd_interval_refine(i, &t);
698d5ac70f0Sopenharmony_ci		}
699d5ac70f0Sopenharmony_ci	} else {
700d5ac70f0Sopenharmony_ci		assert(0);
701d5ac70f0Sopenharmony_ci		return -EINVAL;
702d5ac70f0Sopenharmony_ci	}
703d5ac70f0Sopenharmony_ci	if (changed) {
704d5ac70f0Sopenharmony_ci		params->cmask |= 1 << var;
705d5ac70f0Sopenharmony_ci		params->rmask |= 1 << var;
706d5ac70f0Sopenharmony_ci	}
707d5ac70f0Sopenharmony_ci	return changed;
708d5ac70f0Sopenharmony_ci}
709d5ac70f0Sopenharmony_ci
710d5ac70f0Sopenharmony_ci/* Inside configuration space defined by PARAMS remove from PAR all
711d5ac70f0Sopenharmony_ci   values != VAL. Reduce configuration space accordingly.
712d5ac70f0Sopenharmony_ci   Return -EINVAL if the configuration space is empty
713d5ac70f0Sopenharmony_ci*/
714d5ac70f0Sopenharmony_ciint snd_pcm_hw_param_set(snd_pcm_t *pcm, snd_pcm_hw_params_t *params,
715d5ac70f0Sopenharmony_ci			 snd_set_mode_t mode,
716d5ac70f0Sopenharmony_ci			 snd_pcm_hw_param_t var, unsigned int val, int dir)
717d5ac70f0Sopenharmony_ci{
718d5ac70f0Sopenharmony_ci	snd_pcm_hw_params_t save;
719d5ac70f0Sopenharmony_ci	int err;
720d5ac70f0Sopenharmony_ci	switch (mode) {
721d5ac70f0Sopenharmony_ci	case SND_CHANGE:
722d5ac70f0Sopenharmony_ci		break;
723d5ac70f0Sopenharmony_ci	case SND_TRY:
724d5ac70f0Sopenharmony_ci		save = *params;
725d5ac70f0Sopenharmony_ci		break;
726d5ac70f0Sopenharmony_ci	case SND_TEST:
727d5ac70f0Sopenharmony_ci		save = *params;
728d5ac70f0Sopenharmony_ci		params = &save;
729d5ac70f0Sopenharmony_ci		break;
730d5ac70f0Sopenharmony_ci	default:
731d5ac70f0Sopenharmony_ci		assert(0);
732d5ac70f0Sopenharmony_ci		return -EINVAL;
733d5ac70f0Sopenharmony_ci	}
734d5ac70f0Sopenharmony_ci	err = _snd_pcm_hw_param_set(params, var, val, dir);
735d5ac70f0Sopenharmony_ci	if (err < 0)
736d5ac70f0Sopenharmony_ci		goto _fail;
737d5ac70f0Sopenharmony_ci	if ((mode != SND_TEST || hw_is_interval(var)) && params->rmask) {
738d5ac70f0Sopenharmony_ci		err = snd_pcm_hw_refine(pcm, params);
739d5ac70f0Sopenharmony_ci		if (err < 0)
740d5ac70f0Sopenharmony_ci			goto _fail;
741d5ac70f0Sopenharmony_ci	}
742d5ac70f0Sopenharmony_ci	return 0;
743d5ac70f0Sopenharmony_ci _fail:
744d5ac70f0Sopenharmony_ci	if (mode == SND_TRY)
745d5ac70f0Sopenharmony_ci		*params = save;
746d5ac70f0Sopenharmony_ci	if (err < 0 && mode == SND_TRY)
747d5ac70f0Sopenharmony_ci		dump_hw_params(params, "set", var, val, err);
748d5ac70f0Sopenharmony_ci	return err;
749d5ac70f0Sopenharmony_ci}
750d5ac70f0Sopenharmony_ci
751d5ac70f0Sopenharmony_ciint _snd_pcm_hw_param_set_mask(snd_pcm_hw_params_t *params,
752d5ac70f0Sopenharmony_ci			       snd_pcm_hw_param_t var, const snd_mask_t *val)
753d5ac70f0Sopenharmony_ci{
754d5ac70f0Sopenharmony_ci	int changed;
755d5ac70f0Sopenharmony_ci	assert(hw_is_mask(var));
756d5ac70f0Sopenharmony_ci	changed = snd_mask_refine(hw_param_mask(params, var), val);
757d5ac70f0Sopenharmony_ci	if (changed) {
758d5ac70f0Sopenharmony_ci		params->cmask |= 1 << var;
759d5ac70f0Sopenharmony_ci		params->rmask |= 1 << var;
760d5ac70f0Sopenharmony_ci	}
761d5ac70f0Sopenharmony_ci	return changed;
762d5ac70f0Sopenharmony_ci}
763d5ac70f0Sopenharmony_ci
764d5ac70f0Sopenharmony_ci/* Inside configuration space defined by PARAMS remove from PAR all values
765d5ac70f0Sopenharmony_ci   not contained in MASK. Reduce configuration space accordingly.
766d5ac70f0Sopenharmony_ci   This function can be called only for SND_PCM_HW_PARAM_ACCESS,
767d5ac70f0Sopenharmony_ci   SND_PCM_HW_PARAM_FORMAT, SND_PCM_HW_PARAM_SUBFORMAT.
768d5ac70f0Sopenharmony_ci   Return 0 on success or -EINVAL
769d5ac70f0Sopenharmony_ci   if the configuration space is empty
770d5ac70f0Sopenharmony_ci*/
771d5ac70f0Sopenharmony_ciint snd_pcm_hw_param_set_mask(snd_pcm_t *pcm, snd_pcm_hw_params_t *params,
772d5ac70f0Sopenharmony_ci			      snd_set_mode_t mode,
773d5ac70f0Sopenharmony_ci			      snd_pcm_hw_param_t var, const snd_mask_t *val)
774d5ac70f0Sopenharmony_ci{
775d5ac70f0Sopenharmony_ci	snd_pcm_hw_params_t save;
776d5ac70f0Sopenharmony_ci	int err;
777d5ac70f0Sopenharmony_ci	switch (mode) {
778d5ac70f0Sopenharmony_ci	case SND_CHANGE:
779d5ac70f0Sopenharmony_ci		break;
780d5ac70f0Sopenharmony_ci	case SND_TRY:
781d5ac70f0Sopenharmony_ci		save = *params;
782d5ac70f0Sopenharmony_ci		break;
783d5ac70f0Sopenharmony_ci	case SND_TEST:
784d5ac70f0Sopenharmony_ci		save = *params;
785d5ac70f0Sopenharmony_ci		params = &save;
786d5ac70f0Sopenharmony_ci		break;
787d5ac70f0Sopenharmony_ci	default:
788d5ac70f0Sopenharmony_ci		assert(0);
789d5ac70f0Sopenharmony_ci		return -EINVAL;
790d5ac70f0Sopenharmony_ci	}
791d5ac70f0Sopenharmony_ci	err = _snd_pcm_hw_param_set_mask(params, var, val);
792d5ac70f0Sopenharmony_ci	if (err < 0)
793d5ac70f0Sopenharmony_ci		goto _fail;
794d5ac70f0Sopenharmony_ci	if (mode != SND_TEST && params->rmask) {
795d5ac70f0Sopenharmony_ci		err = snd_pcm_hw_refine(pcm, params);
796d5ac70f0Sopenharmony_ci		if (err < 0)
797d5ac70f0Sopenharmony_ci			goto _fail;
798d5ac70f0Sopenharmony_ci	}
799d5ac70f0Sopenharmony_ci	return 0;
800d5ac70f0Sopenharmony_ci _fail:
801d5ac70f0Sopenharmony_ci	if (mode == SND_TRY)
802d5ac70f0Sopenharmony_ci		*params = save;
803d5ac70f0Sopenharmony_ci	return err;
804d5ac70f0Sopenharmony_ci}
805d5ac70f0Sopenharmony_ci
806d5ac70f0Sopenharmony_ci/* Inside configuration space defined by PARAMS set PAR to the available value
807d5ac70f0Sopenharmony_ci   nearest to VAL. Reduce configuration space accordingly.
808d5ac70f0Sopenharmony_ci   This function cannot be called for SND_PCM_HW_PARAM_ACCESS,
809d5ac70f0Sopenharmony_ci   SND_PCM_HW_PARAM_FORMAT, SND_PCM_HW_PARAM_SUBFORMAT.
810d5ac70f0Sopenharmony_ci   Return the value found.
811d5ac70f0Sopenharmony_ci */
812d5ac70f0Sopenharmony_ciint snd_pcm_hw_param_set_near(snd_pcm_t *pcm, snd_pcm_hw_params_t *params,
813d5ac70f0Sopenharmony_ci			      snd_pcm_hw_param_t var,
814d5ac70f0Sopenharmony_ci			      unsigned int *val, int *dir)
815d5ac70f0Sopenharmony_ci{
816d5ac70f0Sopenharmony_ci	snd_pcm_hw_params_t save;
817d5ac70f0Sopenharmony_ci	int err;
818d5ac70f0Sopenharmony_ci	unsigned int best = *val, saved_min;
819d5ac70f0Sopenharmony_ci	int last = 0;
820d5ac70f0Sopenharmony_ci	unsigned int min, max;
821d5ac70f0Sopenharmony_ci	int mindir, maxdir;
822d5ac70f0Sopenharmony_ci	int valdir = dir ? *dir : 0;
823d5ac70f0Sopenharmony_ci	snd_interval_t *i;
824d5ac70f0Sopenharmony_ci	/* FIXME */
825d5ac70f0Sopenharmony_ci	if (best > INT_MAX)
826d5ac70f0Sopenharmony_ci		best = INT_MAX;
827d5ac70f0Sopenharmony_ci	min = max = best;
828d5ac70f0Sopenharmony_ci	mindir = maxdir = valdir;
829d5ac70f0Sopenharmony_ci	if (maxdir > 0)
830d5ac70f0Sopenharmony_ci		maxdir = 0;
831d5ac70f0Sopenharmony_ci	else if (maxdir == 0)
832d5ac70f0Sopenharmony_ci		maxdir = -1;
833d5ac70f0Sopenharmony_ci	else {
834d5ac70f0Sopenharmony_ci		maxdir = 1;
835d5ac70f0Sopenharmony_ci		max--;
836d5ac70f0Sopenharmony_ci	}
837d5ac70f0Sopenharmony_ci	save = *params;
838d5ac70f0Sopenharmony_ci	saved_min = min;
839d5ac70f0Sopenharmony_ci	err = snd_pcm_hw_param_set_min(pcm, params, SND_CHANGE, var, &min, &mindir);
840d5ac70f0Sopenharmony_ci
841d5ac70f0Sopenharmony_ci	i = hw_param_interval(params, var);
842d5ac70f0Sopenharmony_ci	if (!snd_interval_empty(i) && snd_interval_single(i)) {
843d5ac70f0Sopenharmony_ci		err = snd_pcm_hw_param_get_min(params, var, val, dir);
844d5ac70f0Sopenharmony_ci		if (err < 0)
845d5ac70f0Sopenharmony_ci			dump_hw_params(params, "set_near", var, *val, err);
846d5ac70f0Sopenharmony_ci		return err;
847d5ac70f0Sopenharmony_ci	}
848d5ac70f0Sopenharmony_ci
849d5ac70f0Sopenharmony_ci	if (err >= 0) {
850d5ac70f0Sopenharmony_ci		snd_pcm_hw_params_t params1;
851d5ac70f0Sopenharmony_ci		if (min == saved_min && mindir == valdir)
852d5ac70f0Sopenharmony_ci			goto _end;
853d5ac70f0Sopenharmony_ci		params1 = save;
854d5ac70f0Sopenharmony_ci		err = snd_pcm_hw_param_set_max(pcm, &params1, SND_CHANGE, var, &max, &maxdir);
855d5ac70f0Sopenharmony_ci		if (err < 0)
856d5ac70f0Sopenharmony_ci			goto _end;
857d5ac70f0Sopenharmony_ci		if (boundary_nearer(max, maxdir, best, valdir, min, mindir)) {
858d5ac70f0Sopenharmony_ci			*params = params1;
859d5ac70f0Sopenharmony_ci			last = 1;
860d5ac70f0Sopenharmony_ci		}
861d5ac70f0Sopenharmony_ci	} else {
862d5ac70f0Sopenharmony_ci		*params = save;
863d5ac70f0Sopenharmony_ci		err = snd_pcm_hw_param_set_max(pcm, params, SND_CHANGE, var, &max, &maxdir);
864d5ac70f0Sopenharmony_ci		if (err < 0) {
865d5ac70f0Sopenharmony_ci			dump_hw_params(params, "set_near", var, *val, err);
866d5ac70f0Sopenharmony_ci			return err;
867d5ac70f0Sopenharmony_ci		}
868d5ac70f0Sopenharmony_ci		last = 1;
869d5ac70f0Sopenharmony_ci	}
870d5ac70f0Sopenharmony_ci _end:
871d5ac70f0Sopenharmony_ci	if (last)
872d5ac70f0Sopenharmony_ci		err = snd_pcm_hw_param_set_last(pcm, params, var, val, dir);
873d5ac70f0Sopenharmony_ci	else
874d5ac70f0Sopenharmony_ci		err = snd_pcm_hw_param_set_first(pcm, params, var, val, dir);
875d5ac70f0Sopenharmony_ci	if (err < 0)
876d5ac70f0Sopenharmony_ci		dump_hw_params(params, "set_near", var, *val, err);
877d5ac70f0Sopenharmony_ci	return err;
878d5ac70f0Sopenharmony_ci}
879d5ac70f0Sopenharmony_ci
880d5ac70f0Sopenharmony_ci#if 0
881d5ac70f0Sopenharmony_ci/* Inside configuration space defined by PARAMS set PAR to the available value
882d5ac70f0Sopenharmony_ci   nearest to BEST after VAL (on equal difference values less than BEST are
883d5ac70f0Sopenharmony_ci   returned first).
884d5ac70f0Sopenharmony_ci   Reduce configuration space accordingly.
885d5ac70f0Sopenharmony_ci   This function cannot be called for SND_PCM_HW_PARAM_ACCESS,
886d5ac70f0Sopenharmony_ci   SND_PCM_HW_PARAM_FORMAT, SND_PCM_HW_PARAM_SUBFORMAT.
887d5ac70f0Sopenharmony_ci   Return the value found.
888d5ac70f0Sopenharmony_ci */
889d5ac70f0Sopenharmony_ciint snd_pcm_hw_param_set_next(snd_pcm_t *pcm, snd_pcm_hw_params_t *params,
890d5ac70f0Sopenharmony_ci			      snd_pcm_hw_param_t var,
891d5ac70f0Sopenharmony_ci			      unsigned int best, int bestdir,
892d5ac70f0Sopenharmony_ci			      unsigned int val, int *dir)
893d5ac70f0Sopenharmony_ci{
894d5ac70f0Sopenharmony_ci	snd_pcm_hw_params_t save;
895d5ac70f0Sopenharmony_ci	int v, err;
896d5ac70f0Sopenharmony_ci	int last = 0;
897d5ac70f0Sopenharmony_ci	int min, max;
898d5ac70f0Sopenharmony_ci	int mindir, maxdir;
899d5ac70f0Sopenharmony_ci	int diff, diffdir;
900d5ac70f0Sopenharmony_ci	int valdir = dir ? *dir : 0;
901d5ac70f0Sopenharmony_ci	/* FIXME */
902d5ac70f0Sopenharmony_ci	if (best > INT_MAX)
903d5ac70f0Sopenharmony_ci		best = INT_MAX;
904d5ac70f0Sopenharmony_ci	boundary_sub(val, valdir, best, bestdir, &diff, &diffdir);
905d5ac70f0Sopenharmony_ci	if (diff < 0 || (diff == 0 && diffdir < 0)) {
906d5ac70f0Sopenharmony_ci		min = best - diff;
907d5ac70f0Sopenharmony_ci		mindir = bestdir - diffdir;
908d5ac70f0Sopenharmony_ci		max = val;
909d5ac70f0Sopenharmony_ci		maxdir = bestdir - 1;
910d5ac70f0Sopenharmony_ci	} else {
911d5ac70f0Sopenharmony_ci		min = val;
912d5ac70f0Sopenharmony_ci		mindir = bestdir + 1;
913d5ac70f0Sopenharmony_ci		max = best + diff;
914d5ac70f0Sopenharmony_ci		maxdir = bestdir + diffdir + 1;
915d5ac70f0Sopenharmony_ci	}
916d5ac70f0Sopenharmony_ci	min += mindir / 2;
917d5ac70f0Sopenharmony_ci	mindir %= 2;
918d5ac70f0Sopenharmony_ci	max += maxdir / 2;
919d5ac70f0Sopenharmony_ci	maxdir %= 2;
920d5ac70f0Sopenharmony_ci	save = *params;
921d5ac70f0Sopenharmony_ci	if (min >= 0 &&
922d5ac70f0Sopenharmony_ci	    (err = snd_pcm_hw_param_set_min(pcm, params, SND_CHANGE, var, &min, &mindir)) >= 0) {
923d5ac70f0Sopenharmony_ci		snd_pcm_hw_params_t params1;
924d5ac70f0Sopenharmony_ci		if (max < 0)
925d5ac70f0Sopenharmony_ci			goto _end;
926d5ac70f0Sopenharmony_ci		params1 = save;
927d5ac70f0Sopenharmony_ci		err = snd_pcm_hw_param_set_max(pcm, &params1, SND_CHANGE, var, &max, &maxdir);
928d5ac70f0Sopenharmony_ci		if (err < 0)
929d5ac70f0Sopenharmony_ci			goto _end;
930d5ac70f0Sopenharmony_ci		if (boundary_nearer(max, maxdir, best, bestdir, min, mindir)) {
931d5ac70f0Sopenharmony_ci			*params = params1;
932d5ac70f0Sopenharmony_ci			last = 1;
933d5ac70f0Sopenharmony_ci		}
934d5ac70f0Sopenharmony_ci	} else {
935d5ac70f0Sopenharmony_ci		if (max < 0)
936d5ac70f0Sopenharmony_ci			return -EINVAL;
937d5ac70f0Sopenharmony_ci		*params = save;
938d5ac70f0Sopenharmony_ci		err = snd_pcm_hw_param_set_max(pcm, params, SND_CHANGE, var, &max, &maxdir);
939d5ac70f0Sopenharmony_ci		if (err < 0)
940d5ac70f0Sopenharmony_ci			return max;
941d5ac70f0Sopenharmony_ci		last = 1;
942d5ac70f0Sopenharmony_ci	}
943d5ac70f0Sopenharmony_ci _end:
944d5ac70f0Sopenharmony_ci	if (last)
945d5ac70f0Sopenharmony_ci		v = snd_pcm_hw_param_set_last(pcm, params, var, dir);
946d5ac70f0Sopenharmony_ci	else
947d5ac70f0Sopenharmony_ci		v = snd_pcm_hw_param_set_first(pcm, params, var, dir);
948d5ac70f0Sopenharmony_ci	assert(v >= 0);
949d5ac70f0Sopenharmony_ci	return v;
950d5ac70f0Sopenharmony_ci}
951d5ac70f0Sopenharmony_ci#endif
952d5ac70f0Sopenharmony_ci
953d5ac70f0Sopenharmony_cistatic int snd_pcm_hw_param_set_near_minmax(snd_pcm_t *pcm,
954d5ac70f0Sopenharmony_ci					    snd_pcm_hw_params_t *params,
955d5ac70f0Sopenharmony_ci					    snd_pcm_hw_param_t var,
956d5ac70f0Sopenharmony_ci					    unsigned int min, int *mindir,
957d5ac70f0Sopenharmony_ci					    unsigned int max, int *maxdir)
958d5ac70f0Sopenharmony_ci{
959d5ac70f0Sopenharmony_ci	snd_pcm_hw_params_t tmp;
960d5ac70f0Sopenharmony_ci	int err;
961d5ac70f0Sopenharmony_ci	if (!boundary_lt(min, *mindir, max, *maxdir))
962d5ac70f0Sopenharmony_ci		return snd_pcm_hw_param_set_near(pcm, params, var, &min, mindir);
963d5ac70f0Sopenharmony_ci	tmp = *params;
964d5ac70f0Sopenharmony_ci	err = snd_pcm_hw_param_set_near(pcm, &tmp, var, &min, mindir);
965d5ac70f0Sopenharmony_ci	if (err < 0)
966d5ac70f0Sopenharmony_ci		return err;
967d5ac70f0Sopenharmony_ci	if (boundary_lt(min, *mindir, max, *maxdir)) {
968d5ac70f0Sopenharmony_ci		tmp = *params;
969d5ac70f0Sopenharmony_ci		err = snd_pcm_hw_param_set_near(pcm, &tmp, var, &max, maxdir);
970d5ac70f0Sopenharmony_ci	} else {
971d5ac70f0Sopenharmony_ci		max = min;
972d5ac70f0Sopenharmony_ci		*maxdir = *mindir;
973d5ac70f0Sopenharmony_ci	}
974d5ac70f0Sopenharmony_ci	err = snd_pcm_hw_param_set_minmax(pcm, params, SND_CHANGE, var, &min, mindir,
975d5ac70f0Sopenharmony_ci					  &max, maxdir);
976d5ac70f0Sopenharmony_ci	if (err < 0)
977d5ac70f0Sopenharmony_ci		return err;
978d5ac70f0Sopenharmony_ci	return 0;
979d5ac70f0Sopenharmony_ci}
980d5ac70f0Sopenharmony_ci
981d5ac70f0Sopenharmony_ciint snd_pcm_hw_param_refine_near(snd_pcm_t *pcm,
982d5ac70f0Sopenharmony_ci				 snd_pcm_hw_params_t *params,
983d5ac70f0Sopenharmony_ci				 snd_pcm_hw_param_t var,
984d5ac70f0Sopenharmony_ci				 const snd_pcm_hw_params_t *src)
985d5ac70f0Sopenharmony_ci{
986d5ac70f0Sopenharmony_ci	unsigned int min, max;
987d5ac70f0Sopenharmony_ci	int mindir, maxdir, err;
988d5ac70f0Sopenharmony_ci
989d5ac70f0Sopenharmony_ci	if ((err = snd_pcm_hw_param_get_min(src, var, &min, &mindir)) < 0)
990d5ac70f0Sopenharmony_ci		return err;
991d5ac70f0Sopenharmony_ci	if ((err = snd_pcm_hw_param_get_max(src, var, &max, &maxdir)) < 0)
992d5ac70f0Sopenharmony_ci		return err;
993d5ac70f0Sopenharmony_ci	if ((err = snd_pcm_hw_param_set_near_minmax(pcm, params, var,
994d5ac70f0Sopenharmony_ci						    min, &mindir, max, &maxdir)) < 0)
995d5ac70f0Sopenharmony_ci		return err;
996d5ac70f0Sopenharmony_ci	return 0;
997d5ac70f0Sopenharmony_ci}
998d5ac70f0Sopenharmony_ci
999d5ac70f0Sopenharmony_ciint snd_pcm_hw_param_refine_multiple(snd_pcm_t *pcm,
1000d5ac70f0Sopenharmony_ci				     snd_pcm_hw_params_t *params,
1001d5ac70f0Sopenharmony_ci				     snd_pcm_hw_param_t var,
1002d5ac70f0Sopenharmony_ci				     const snd_pcm_hw_params_t *src)
1003d5ac70f0Sopenharmony_ci{
1004d5ac70f0Sopenharmony_ci	const snd_interval_t *it = hw_param_interval_c(src, var);
1005d5ac70f0Sopenharmony_ci	const snd_interval_t *st = hw_param_interval_c(params, var);
1006d5ac70f0Sopenharmony_ci	if (snd_interval_single(it)) {
1007d5ac70f0Sopenharmony_ci		unsigned int best = snd_interval_min(it), cur, prev;
1008d5ac70f0Sopenharmony_ci		cur = best;
1009d5ac70f0Sopenharmony_ci		for (;;) {
1010d5ac70f0Sopenharmony_ci			if (st->max < cur || (st->max == cur && st->openmax))
1011d5ac70f0Sopenharmony_ci				break;
1012d5ac70f0Sopenharmony_ci			if (it->min <= cur && ! (it->min == cur && st->openmin)) {
1013d5ac70f0Sopenharmony_ci				if (! snd_pcm_hw_param_set(pcm, params, SND_TRY, var, cur, 0))
1014d5ac70f0Sopenharmony_ci					return 0; /* ok */
1015d5ac70f0Sopenharmony_ci			}
1016d5ac70f0Sopenharmony_ci			prev = cur;
1017d5ac70f0Sopenharmony_ci			cur += best;
1018d5ac70f0Sopenharmony_ci			if (cur <= prev)
1019d5ac70f0Sopenharmony_ci				break;
1020d5ac70f0Sopenharmony_ci		}
1021d5ac70f0Sopenharmony_ci	}
1022d5ac70f0Sopenharmony_ci	return snd_pcm_hw_param_refine_near(pcm, params, var, src);
1023d5ac70f0Sopenharmony_ci}
1024d5ac70f0Sopenharmony_ci
1025d5ac70f0Sopenharmony_ci/* ---- end of refinement functions ---- */
1026d5ac70f0Sopenharmony_ci
1027d5ac70f0Sopenharmony_ciint snd_pcm_hw_param_empty(const snd_pcm_hw_params_t *params,
1028d5ac70f0Sopenharmony_ci			   snd_pcm_hw_param_t var)
1029d5ac70f0Sopenharmony_ci{
1030d5ac70f0Sopenharmony_ci	if (hw_is_mask(var))
1031d5ac70f0Sopenharmony_ci		return snd_mask_empty(hw_param_mask_c(params, var));
1032d5ac70f0Sopenharmony_ci	if (hw_is_interval(var))
1033d5ac70f0Sopenharmony_ci		return snd_interval_empty(hw_param_interval_c(params, var));
1034d5ac70f0Sopenharmony_ci	assert(0);
1035d5ac70f0Sopenharmony_ci	return -EINVAL;
1036d5ac70f0Sopenharmony_ci}
1037d5ac70f0Sopenharmony_ci
1038d5ac70f0Sopenharmony_ciint snd_pcm_hw_param_always_eq(const snd_pcm_hw_params_t *params,
1039d5ac70f0Sopenharmony_ci			       snd_pcm_hw_param_t var,
1040d5ac70f0Sopenharmony_ci			       const snd_pcm_hw_params_t *params1)
1041d5ac70f0Sopenharmony_ci{
1042d5ac70f0Sopenharmony_ci	if (hw_is_mask(var))
1043d5ac70f0Sopenharmony_ci		return snd_mask_always_eq(hw_param_mask_c(params, var),
1044d5ac70f0Sopenharmony_ci					  hw_param_mask_c(params1, var));
1045d5ac70f0Sopenharmony_ci	if (hw_is_interval(var))
1046d5ac70f0Sopenharmony_ci		return snd_interval_always_eq(hw_param_interval_c(params, var),
1047d5ac70f0Sopenharmony_ci					      hw_param_interval_c(params1, var));
1048d5ac70f0Sopenharmony_ci	assert(0);
1049d5ac70f0Sopenharmony_ci	return -EINVAL;
1050d5ac70f0Sopenharmony_ci}
1051d5ac70f0Sopenharmony_ci
1052d5ac70f0Sopenharmony_ciint snd_pcm_hw_param_never_eq(const snd_pcm_hw_params_t *params,
1053d5ac70f0Sopenharmony_ci			      snd_pcm_hw_param_t var,
1054d5ac70f0Sopenharmony_ci			      const snd_pcm_hw_params_t *params1)
1055d5ac70f0Sopenharmony_ci{
1056d5ac70f0Sopenharmony_ci	if (hw_is_mask(var))
1057d5ac70f0Sopenharmony_ci		return snd_mask_never_eq(hw_param_mask_c(params, var),
1058d5ac70f0Sopenharmony_ci					 hw_param_mask_c(params1, var));
1059d5ac70f0Sopenharmony_ci	if (hw_is_interval(var))
1060d5ac70f0Sopenharmony_ci		return snd_interval_never_eq(hw_param_interval_c(params, var),
1061d5ac70f0Sopenharmony_ci					     hw_param_interval_c(params1, var));
1062d5ac70f0Sopenharmony_ci	assert(0);
1063d5ac70f0Sopenharmony_ci	return -EINVAL;
1064d5ac70f0Sopenharmony_ci}
1065d5ac70f0Sopenharmony_ci
1066d5ac70f0Sopenharmony_ci#if 0
1067d5ac70f0Sopenharmony_ci#define CHOOSE_DEBUG
1068d5ac70f0Sopenharmony_ci#endif
1069d5ac70f0Sopenharmony_ci
1070d5ac70f0Sopenharmony_ci/* Choose one configuration from configuration space defined by PARAMS
1071d5ac70f0Sopenharmony_ci   The configuration chosen is that obtained fixing in this order:
1072d5ac70f0Sopenharmony_ci   first access
1073d5ac70f0Sopenharmony_ci   first format
1074d5ac70f0Sopenharmony_ci   first subformat
1075d5ac70f0Sopenharmony_ci   min channels
1076d5ac70f0Sopenharmony_ci   min rate
1077d5ac70f0Sopenharmony_ci   min period time
1078d5ac70f0Sopenharmony_ci   max buffer size
1079d5ac70f0Sopenharmony_ci   min tick time
1080d5ac70f0Sopenharmony_ci*/
1081d5ac70f0Sopenharmony_cistatic int snd_pcm_hw_params_choose(snd_pcm_t *pcm, snd_pcm_hw_params_t *params)
1082d5ac70f0Sopenharmony_ci{
1083d5ac70f0Sopenharmony_ci	int err;
1084d5ac70f0Sopenharmony_ci#ifdef CHOOSE_DEBUG
1085d5ac70f0Sopenharmony_ci	snd_output_t *log;
1086d5ac70f0Sopenharmony_ci	snd_output_stdio_attach(&log, stderr, 0);
1087d5ac70f0Sopenharmony_ci	snd_output_printf(log, "CHOOSE called:\n");
1088d5ac70f0Sopenharmony_ci	snd_pcm_hw_params_dump(params, log);
1089d5ac70f0Sopenharmony_ci#endif
1090d5ac70f0Sopenharmony_ci
1091d5ac70f0Sopenharmony_ci	err = snd_pcm_hw_param_set_first(pcm, params, SND_PCM_HW_PARAM_ACCESS, NULL, 0);
1092d5ac70f0Sopenharmony_ci	if (err < 0)
1093d5ac70f0Sopenharmony_ci		return err;
1094d5ac70f0Sopenharmony_ci	err = snd_pcm_hw_param_set_first(pcm, params, SND_PCM_HW_PARAM_FORMAT, NULL, 0);
1095d5ac70f0Sopenharmony_ci	if (err < 0)
1096d5ac70f0Sopenharmony_ci		return err;
1097d5ac70f0Sopenharmony_ci	err = snd_pcm_hw_param_set_first(pcm, params, SND_PCM_HW_PARAM_SUBFORMAT, NULL, 0);
1098d5ac70f0Sopenharmony_ci	if (err < 0)
1099d5ac70f0Sopenharmony_ci		return err;
1100d5ac70f0Sopenharmony_ci	err = snd_pcm_hw_param_set_first(pcm, params, SND_PCM_HW_PARAM_CHANNELS, NULL, 0);
1101d5ac70f0Sopenharmony_ci	if (err < 0)
1102d5ac70f0Sopenharmony_ci		return err;
1103d5ac70f0Sopenharmony_ci	err = snd_pcm_hw_param_set_first(pcm, params, SND_PCM_HW_PARAM_RATE, NULL, 0);
1104d5ac70f0Sopenharmony_ci	if (err < 0)
1105d5ac70f0Sopenharmony_ci		return err;
1106d5ac70f0Sopenharmony_ci	if (pcm->minperiodtime > 0) {
1107d5ac70f0Sopenharmony_ci		unsigned int min, max;
1108d5ac70f0Sopenharmony_ci		int dir = 1;
1109d5ac70f0Sopenharmony_ci		err = snd_pcm_hw_param_get_min(params, SND_PCM_HW_PARAM_PERIOD_TIME, &min, &dir);
1110d5ac70f0Sopenharmony_ci		if (err >= 0)
1111d5ac70f0Sopenharmony_ci			err = snd_pcm_hw_param_get_max(params, SND_PCM_HW_PARAM_PERIOD_TIME, &max, &dir);
1112d5ac70f0Sopenharmony_ci		if (err >= 0 && (long)min < pcm->minperiodtime &&
1113d5ac70f0Sopenharmony_ci			        (long)max > pcm->minperiodtime) {
1114d5ac70f0Sopenharmony_ci			min = pcm->minperiodtime; dir = 1;
1115d5ac70f0Sopenharmony_ci			snd_pcm_hw_param_set_min(pcm, params, SND_CHANGE, SND_PCM_HW_PARAM_PERIOD_TIME, &min, &dir);
1116d5ac70f0Sopenharmony_ci		}
1117d5ac70f0Sopenharmony_ci	}
1118d5ac70f0Sopenharmony_ci	if (pcm->compat) {
1119d5ac70f0Sopenharmony_ci		/* old mode */
1120d5ac70f0Sopenharmony_ci		err = snd_pcm_hw_param_set_first(pcm, params, SND_PCM_HW_PARAM_PERIOD_TIME, NULL, 0);
1121d5ac70f0Sopenharmony_ci		if (err < 0)
1122d5ac70f0Sopenharmony_ci			return err;
1123d5ac70f0Sopenharmony_ci		err = snd_pcm_hw_param_set_first(pcm, params, SND_PCM_HW_PARAM_PERIOD_SIZE, NULL, 0);
1124d5ac70f0Sopenharmony_ci		if (err < 0)
1125d5ac70f0Sopenharmony_ci			return err;
1126d5ac70f0Sopenharmony_ci		err = snd_pcm_hw_param_set_last(pcm, params, SND_PCM_HW_PARAM_BUFFER_SIZE, NULL, 0);
1127d5ac70f0Sopenharmony_ci		if (err < 0)
1128d5ac70f0Sopenharmony_ci			return err;
1129d5ac70f0Sopenharmony_ci	} else {
1130d5ac70f0Sopenharmony_ci		/* determine buffer size first */
1131d5ac70f0Sopenharmony_ci		err = snd_pcm_hw_param_set_last(pcm, params, SND_PCM_HW_PARAM_BUFFER_SIZE, NULL, 0);
1132d5ac70f0Sopenharmony_ci		if (err < 0)
1133d5ac70f0Sopenharmony_ci			return err;
1134d5ac70f0Sopenharmony_ci		err = snd_pcm_hw_param_set_first(pcm, params, SND_PCM_HW_PARAM_PERIOD_SIZE, NULL, 0);
1135d5ac70f0Sopenharmony_ci		if (err < 0)
1136d5ac70f0Sopenharmony_ci			return err;
1137d5ac70f0Sopenharmony_ci		err = snd_pcm_hw_param_set_first(pcm, params, SND_PCM_HW_PARAM_PERIOD_TIME, NULL, 0);
1138d5ac70f0Sopenharmony_ci		if (err < 0)
1139d5ac70f0Sopenharmony_ci			return err;
1140d5ac70f0Sopenharmony_ci	}
1141d5ac70f0Sopenharmony_ci	err = snd_pcm_hw_param_set_first(pcm, params, SND_PCM_HW_PARAM_TICK_TIME, NULL, 0);
1142d5ac70f0Sopenharmony_ci	if (err < 0)
1143d5ac70f0Sopenharmony_ci		return err;
1144d5ac70f0Sopenharmony_ci#ifdef CHOOSE_DEBUG
1145d5ac70f0Sopenharmony_ci	snd_output_printf(log, "choose done\n");
1146d5ac70f0Sopenharmony_ci	snd_pcm_hw_params_dump(params, log);
1147d5ac70f0Sopenharmony_ci	snd_output_close(log);
1148d5ac70f0Sopenharmony_ci#endif
1149d5ac70f0Sopenharmony_ci	return 0;
1150d5ac70f0Sopenharmony_ci}
1151d5ac70f0Sopenharmony_ci
1152d5ac70f0Sopenharmony_ci#if 0
1153d5ac70f0Sopenharmony_cistatic unsigned int snd_pcm_hw_param_count(const snd_pcm_hw_params_t *params,
1154d5ac70f0Sopenharmony_ci					   snd_pcm_hw_param_t var)
1155d5ac70f0Sopenharmony_ci{
1156d5ac70f0Sopenharmony_ci	if (hw_is_mask(var)) {
1157d5ac70f0Sopenharmony_ci		const snd_mask_t *mask = hw_param_mask_c(params, var);
1158d5ac70f0Sopenharmony_ci		return snd_mask_count(mask);
1159d5ac70f0Sopenharmony_ci	}
1160d5ac70f0Sopenharmony_ci	if (hw_is_interval(var)) {
1161d5ac70f0Sopenharmony_ci		const snd_interval_t *i = hw_param_interval_c(params, var);
1162d5ac70f0Sopenharmony_ci		return snd_interval_max(i) - snd_interval_min(i) + 1;
1163d5ac70f0Sopenharmony_ci	}
1164d5ac70f0Sopenharmony_ci	assert(0);
1165d5ac70f0Sopenharmony_ci	return 0;
1166d5ac70f0Sopenharmony_ci}
1167d5ac70f0Sopenharmony_ci#endif
1168d5ac70f0Sopenharmony_ci
1169d5ac70f0Sopenharmony_ciint _snd_pcm_hw_param_refine(snd_pcm_hw_params_t *params,
1170d5ac70f0Sopenharmony_ci			     snd_pcm_hw_param_t var,
1171d5ac70f0Sopenharmony_ci			     const snd_pcm_hw_params_t *src)
1172d5ac70f0Sopenharmony_ci{
1173d5ac70f0Sopenharmony_ci	int changed = 0;
1174d5ac70f0Sopenharmony_ci	if (hw_is_mask(var)) {
1175d5ac70f0Sopenharmony_ci		snd_mask_t *d = hw_param_mask(params, var);
1176d5ac70f0Sopenharmony_ci		const snd_mask_t *s = hw_param_mask_c(src, var);
1177d5ac70f0Sopenharmony_ci		changed = snd_mask_refine(d, s);
1178d5ac70f0Sopenharmony_ci	} else if (hw_is_interval(var)) {
1179d5ac70f0Sopenharmony_ci		snd_interval_t *d = hw_param_interval(params, var);
1180d5ac70f0Sopenharmony_ci		const snd_interval_t *s = hw_param_interval_c(src, var);
1181d5ac70f0Sopenharmony_ci		changed = snd_interval_refine(d, s);
1182d5ac70f0Sopenharmony_ci	} else
1183d5ac70f0Sopenharmony_ci		return 0; /* NOP / reserved */
1184d5ac70f0Sopenharmony_ci	if (changed) {
1185d5ac70f0Sopenharmony_ci		params->cmask |= 1 << var;
1186d5ac70f0Sopenharmony_ci		params->rmask |= 1 << var;
1187d5ac70f0Sopenharmony_ci	}
1188d5ac70f0Sopenharmony_ci	return changed;
1189d5ac70f0Sopenharmony_ci}
1190d5ac70f0Sopenharmony_ci
1191d5ac70f0Sopenharmony_ci#if 0
1192d5ac70f0Sopenharmony_cistatic void _snd_pcm_hw_param_copy(snd_pcm_hw_params_t *params, snd_pcm_hw_param_t var,
1193d5ac70f0Sopenharmony_ci				   const snd_pcm_hw_params_t *src)
1194d5ac70f0Sopenharmony_ci{
1195d5ac70f0Sopenharmony_ci	if (hw_is_mask(var)) {
1196d5ac70f0Sopenharmony_ci		snd_mask_t *d = hw_param_mask(params, var);
1197d5ac70f0Sopenharmony_ci		const snd_mask_t *s = hw_param_mask_c(src, var);
1198d5ac70f0Sopenharmony_ci		snd_mask_copy(d, s);
1199d5ac70f0Sopenharmony_ci		params->cmask |= 1 << var;
1200d5ac70f0Sopenharmony_ci		params->rmask |= 1 << var;
1201d5ac70f0Sopenharmony_ci		return;
1202d5ac70f0Sopenharmony_ci	}
1203d5ac70f0Sopenharmony_ci	if (hw_is_interval(var)) {
1204d5ac70f0Sopenharmony_ci		snd_interval_t *d = hw_param_interval(params, var);
1205d5ac70f0Sopenharmony_ci		const snd_interval_t *s = hw_param_interval_c(src, var);
1206d5ac70f0Sopenharmony_ci		snd_interval_copy(d, s);
1207d5ac70f0Sopenharmony_ci		params->cmask |= 1 << var;
1208d5ac70f0Sopenharmony_ci		params->rmask |= 1 << var;
1209d5ac70f0Sopenharmony_ci		return;
1210d5ac70f0Sopenharmony_ci	}
1211d5ac70f0Sopenharmony_ci	assert(0);
1212d5ac70f0Sopenharmony_ci}
1213d5ac70f0Sopenharmony_ci#endif
1214d5ac70f0Sopenharmony_ci
1215d5ac70f0Sopenharmony_civoid snd_pcm_hw_param_dump(const snd_pcm_hw_params_t *params,
1216d5ac70f0Sopenharmony_ci			   snd_pcm_hw_param_t var, snd_output_t *out)
1217d5ac70f0Sopenharmony_ci{
1218d5ac70f0Sopenharmony_ci	if (hw_is_mask(var)) {
1219d5ac70f0Sopenharmony_ci		const snd_mask_t *mask = hw_param_mask_c(params, var);
1220d5ac70f0Sopenharmony_ci		if (snd_mask_empty(mask))
1221d5ac70f0Sopenharmony_ci			snd_output_puts(out, " NONE");
1222d5ac70f0Sopenharmony_ci		else if (snd_mask_full(mask))
1223d5ac70f0Sopenharmony_ci			snd_output_puts(out, " ALL");
1224d5ac70f0Sopenharmony_ci		else {
1225d5ac70f0Sopenharmony_ci			unsigned int k;
1226d5ac70f0Sopenharmony_ci			for (k = 0; k <= SND_MASK_MAX; ++k) {
1227d5ac70f0Sopenharmony_ci				if (snd_mask_test(mask, k)) {
1228d5ac70f0Sopenharmony_ci					const char *s;
1229d5ac70f0Sopenharmony_ci					switch (var) {
1230d5ac70f0Sopenharmony_ci					case SND_PCM_HW_PARAM_ACCESS:
1231d5ac70f0Sopenharmony_ci						s = snd_pcm_access_name(k);
1232d5ac70f0Sopenharmony_ci						break;
1233d5ac70f0Sopenharmony_ci					case SND_PCM_HW_PARAM_FORMAT:
1234d5ac70f0Sopenharmony_ci						s = snd_pcm_format_name(k);
1235d5ac70f0Sopenharmony_ci						break;
1236d5ac70f0Sopenharmony_ci					case SND_PCM_HW_PARAM_SUBFORMAT:
1237d5ac70f0Sopenharmony_ci						s = snd_pcm_subformat_name(k);
1238d5ac70f0Sopenharmony_ci						break;
1239d5ac70f0Sopenharmony_ci					default:
1240d5ac70f0Sopenharmony_ci						assert(0);
1241d5ac70f0Sopenharmony_ci						s = NULL;
1242d5ac70f0Sopenharmony_ci					}
1243d5ac70f0Sopenharmony_ci					if (s) {
1244d5ac70f0Sopenharmony_ci						snd_output_putc(out, ' ');
1245d5ac70f0Sopenharmony_ci						snd_output_puts(out, s);
1246d5ac70f0Sopenharmony_ci					}
1247d5ac70f0Sopenharmony_ci				}
1248d5ac70f0Sopenharmony_ci			}
1249d5ac70f0Sopenharmony_ci		}
1250d5ac70f0Sopenharmony_ci		return;
1251d5ac70f0Sopenharmony_ci	}
1252d5ac70f0Sopenharmony_ci	if (hw_is_interval(var)) {
1253d5ac70f0Sopenharmony_ci		snd_interval_print(hw_param_interval_c(params, var), out);
1254d5ac70f0Sopenharmony_ci		return;
1255d5ac70f0Sopenharmony_ci	}
1256d5ac70f0Sopenharmony_ci	assert(0);
1257d5ac70f0Sopenharmony_ci}
1258d5ac70f0Sopenharmony_ci
1259d5ac70f0Sopenharmony_ci#define HW_PARAM(v) [SND_PCM_HW_PARAM_##v] = #v
1260d5ac70f0Sopenharmony_ci
1261d5ac70f0Sopenharmony_cistatic const char *const snd_pcm_hw_param_names[] = {
1262d5ac70f0Sopenharmony_ci	HW_PARAM(ACCESS),
1263d5ac70f0Sopenharmony_ci	HW_PARAM(FORMAT),
1264d5ac70f0Sopenharmony_ci	HW_PARAM(SUBFORMAT),
1265d5ac70f0Sopenharmony_ci	HW_PARAM(SAMPLE_BITS),
1266d5ac70f0Sopenharmony_ci	HW_PARAM(FRAME_BITS),
1267d5ac70f0Sopenharmony_ci	HW_PARAM(CHANNELS),
1268d5ac70f0Sopenharmony_ci	HW_PARAM(RATE),
1269d5ac70f0Sopenharmony_ci	HW_PARAM(PERIOD_TIME),
1270d5ac70f0Sopenharmony_ci	HW_PARAM(PERIOD_SIZE),
1271d5ac70f0Sopenharmony_ci	HW_PARAM(PERIOD_BYTES),
1272d5ac70f0Sopenharmony_ci	HW_PARAM(PERIODS),
1273d5ac70f0Sopenharmony_ci	HW_PARAM(BUFFER_TIME),
1274d5ac70f0Sopenharmony_ci	HW_PARAM(BUFFER_SIZE),
1275d5ac70f0Sopenharmony_ci	HW_PARAM(BUFFER_BYTES),
1276d5ac70f0Sopenharmony_ci	HW_PARAM(TICK_TIME),
1277d5ac70f0Sopenharmony_ci};
1278d5ac70f0Sopenharmony_ci
1279d5ac70f0Sopenharmony_ciconst char *snd_pcm_hw_param_name(snd_pcm_hw_param_t param)
1280d5ac70f0Sopenharmony_ci{
1281d5ac70f0Sopenharmony_ci	assert(param <= SND_PCM_HW_PARAM_LAST_INTERVAL);
1282d5ac70f0Sopenharmony_ci	return snd_pcm_hw_param_names[param];
1283d5ac70f0Sopenharmony_ci}
1284d5ac70f0Sopenharmony_ci
1285d5ac70f0Sopenharmony_ci#if 0
1286d5ac70f0Sopenharmony_ci/* Strategies */
1287d5ac70f0Sopenharmony_ci
1288d5ac70f0Sopenharmony_cistruct _snd_pcm_hw_strategy {
1289d5ac70f0Sopenharmony_ci	unsigned int badness_min, badness_max;
1290d5ac70f0Sopenharmony_ci	int (*choose_param)(const snd_pcm_hw_params_t *params,
1291d5ac70f0Sopenharmony_ci			    snd_pcm_t *pcm,
1292d5ac70f0Sopenharmony_ci			    const snd_pcm_hw_strategy_t *strategy);
1293d5ac70f0Sopenharmony_ci	int (*next_value)(snd_pcm_hw_params_t *params,
1294d5ac70f0Sopenharmony_ci			  unsigned int param,
1295d5ac70f0Sopenharmony_ci			  int value, int *dir,
1296d5ac70f0Sopenharmony_ci			  snd_pcm_t *pcm,
1297d5ac70f0Sopenharmony_ci			  const snd_pcm_hw_strategy_t *strategy);
1298d5ac70f0Sopenharmony_ci	int (*min_badness)(const snd_pcm_hw_params_t *params,
1299d5ac70f0Sopenharmony_ci			   unsigned int max_badness,
1300d5ac70f0Sopenharmony_ci			   snd_pcm_t *pcm,
1301d5ac70f0Sopenharmony_ci			   const snd_pcm_hw_strategy_t *strategy);
1302d5ac70f0Sopenharmony_ci	void *private_data;
1303d5ac70f0Sopenharmony_ci	void (*free)(snd_pcm_hw_strategy_t *strategy);
1304d5ac70f0Sopenharmony_ci};
1305d5ac70f0Sopenharmony_ci
1306d5ac70f0Sopenharmony_ci/* Independent badness */
1307d5ac70f0Sopenharmony_citypedef struct _snd_pcm_hw_strategy_simple snd_pcm_hw_strategy_simple_t;
1308d5ac70f0Sopenharmony_ci
1309d5ac70f0Sopenharmony_cistruct _snd_pcm_hw_strategy_simple {
1310d5ac70f0Sopenharmony_ci	int valid;
1311d5ac70f0Sopenharmony_ci	unsigned int order;
1312d5ac70f0Sopenharmony_ci	int (*next_value)(snd_pcm_hw_params_t *params,
1313d5ac70f0Sopenharmony_ci			  unsigned int param,
1314d5ac70f0Sopenharmony_ci			  int value, int *dir,
1315d5ac70f0Sopenharmony_ci			  snd_pcm_t *pcm,
1316d5ac70f0Sopenharmony_ci			  const snd_pcm_hw_strategy_simple_t *par);
1317d5ac70f0Sopenharmony_ci	unsigned int (*min_badness)(const snd_pcm_hw_params_t *params,
1318d5ac70f0Sopenharmony_ci				    unsigned int param,
1319d5ac70f0Sopenharmony_ci				    snd_pcm_t *pcm,
1320d5ac70f0Sopenharmony_ci				    const snd_pcm_hw_strategy_simple_t *par);
1321d5ac70f0Sopenharmony_ci	void *private_data;
1322d5ac70f0Sopenharmony_ci	void (*free)(snd_pcm_hw_strategy_simple_t *strategy);
1323d5ac70f0Sopenharmony_ci};
1324d5ac70f0Sopenharmony_ci
1325d5ac70f0Sopenharmony_citypedef struct _snd_pcm_hw_strategy_simple_near {
1326d5ac70f0Sopenharmony_ci	int best;
1327d5ac70f0Sopenharmony_ci	unsigned int mul;
1328d5ac70f0Sopenharmony_ci} snd_pcm_hw_strategy_simple_near_t;
1329d5ac70f0Sopenharmony_ci
1330d5ac70f0Sopenharmony_citypedef struct _snd_pcm_hw_strategy_simple_choices {
1331d5ac70f0Sopenharmony_ci	unsigned int count;
1332d5ac70f0Sopenharmony_ci	/* choices need to be sorted on ascending badness */
1333d5ac70f0Sopenharmony_ci	snd_pcm_hw_strategy_simple_choices_list_t *choices;
1334d5ac70f0Sopenharmony_ci} snd_pcm_hw_strategy_simple_choices_t;
1335d5ac70f0Sopenharmony_ci
1336d5ac70f0Sopenharmony_ciint snd_pcm_hw_params_strategy(snd_pcm_t *pcm, snd_pcm_hw_params_t *params,
1337d5ac70f0Sopenharmony_ci			       const snd_pcm_hw_strategy_t *strategy,
1338d5ac70f0Sopenharmony_ci			       unsigned int badness_min,
1339d5ac70f0Sopenharmony_ci			       unsigned int badness_max)
1340d5ac70f0Sopenharmony_ci{
1341d5ac70f0Sopenharmony_ci	snd_pcm_hw_params_t best_params;
1342d5ac70f0Sopenharmony_ci	int var;
1343d5ac70f0Sopenharmony_ci	int value, dir;
1344d5ac70f0Sopenharmony_ci	unsigned int best_badness;
1345d5ac70f0Sopenharmony_ci	int badness = strategy->min_badness(params, badness_max, pcm, strategy);
1346d5ac70f0Sopenharmony_ci	snd_pcm_hw_params_t params1;
1347d5ac70f0Sopenharmony_ci#if 0
1348d5ac70f0Sopenharmony_ci	printf("\nBadness: %d\n", badness);
1349d5ac70f0Sopenharmony_ci	snd_pcm_hw_params_dump(params, stdout);
1350d5ac70f0Sopenharmony_ci#endif
1351d5ac70f0Sopenharmony_ci	if (badness < 0)
1352d5ac70f0Sopenharmony_ci		return badness;
1353d5ac70f0Sopenharmony_ci	if ((unsigned int)badness > badness_min)
1354d5ac70f0Sopenharmony_ci		badness_min = badness_min;
1355d5ac70f0Sopenharmony_ci	var = strategy->choose_param(params, pcm, strategy);
1356d5ac70f0Sopenharmony_ci	if (var < 0)
1357d5ac70f0Sopenharmony_ci		return badness;
1358d5ac70f0Sopenharmony_ci	best_badness = UINT_MAX;
1359d5ac70f0Sopenharmony_ci	value = -1;
1360d5ac70f0Sopenharmony_ci	while (1) {
1361d5ac70f0Sopenharmony_ci		params1 = *params;
1362d5ac70f0Sopenharmony_ci		value = strategy->next_value(&params1, var, value, &dir, pcm, strategy);
1363d5ac70f0Sopenharmony_ci		if (value < 0)
1364d5ac70f0Sopenharmony_ci			break;
1365d5ac70f0Sopenharmony_ci		badness = snd_pcm_hw_params_strategy(pcm, &params1, strategy, badness_min, badness_max);
1366d5ac70f0Sopenharmony_ci		if (badness >= 0) {
1367d5ac70f0Sopenharmony_ci			if ((unsigned int) badness <= badness_min) {
1368d5ac70f0Sopenharmony_ci				*params = params1;
1369d5ac70f0Sopenharmony_ci				return badness;
1370d5ac70f0Sopenharmony_ci			}
1371d5ac70f0Sopenharmony_ci			best_badness = badness;
1372d5ac70f0Sopenharmony_ci			best_params = params1;
1373d5ac70f0Sopenharmony_ci			badness_max = badness - 1;
1374d5ac70f0Sopenharmony_ci		}
1375d5ac70f0Sopenharmony_ci	}
1376d5ac70f0Sopenharmony_ci	if (best_badness == UINT_MAX) {
1377d5ac70f0Sopenharmony_ci		return -EINVAL;
1378d5ac70f0Sopenharmony_ci	}
1379d5ac70f0Sopenharmony_ci	*params = best_params;
1380d5ac70f0Sopenharmony_ci	return best_badness;
1381d5ac70f0Sopenharmony_ci}
1382d5ac70f0Sopenharmony_ci
1383d5ac70f0Sopenharmony_civoid snd_pcm_hw_strategy_simple_free(snd_pcm_hw_strategy_t *strategy)
1384d5ac70f0Sopenharmony_ci{
1385d5ac70f0Sopenharmony_ci	snd_pcm_hw_strategy_simple_t *pars = strategy->private_data;
1386d5ac70f0Sopenharmony_ci	int k;
1387d5ac70f0Sopenharmony_ci	for (k = 0; k <= SND_PCM_HW_PARAM_LAST_INTERVAL; ++k) {
1388d5ac70f0Sopenharmony_ci		if (pars[k].valid && pars[k].free)
1389d5ac70f0Sopenharmony_ci			pars[k].free(&pars[k]);
1390d5ac70f0Sopenharmony_ci	}
1391d5ac70f0Sopenharmony_ci	free(pars);
1392d5ac70f0Sopenharmony_ci}
1393d5ac70f0Sopenharmony_ci
1394d5ac70f0Sopenharmony_ciint snd_pcm_hw_strategy_simple_choose_param(const snd_pcm_hw_params_t *params,
1395d5ac70f0Sopenharmony_ci					 snd_pcm_t *pcm ATTRIBUTE_UNUSED,
1396d5ac70f0Sopenharmony_ci					 const snd_pcm_hw_strategy_t *strategy)
1397d5ac70f0Sopenharmony_ci{
1398d5ac70f0Sopenharmony_ci	snd_pcm_hw_param_t var;
1399d5ac70f0Sopenharmony_ci	int best_var = -1;
1400d5ac70f0Sopenharmony_ci	const snd_pcm_hw_strategy_simple_t *pars = strategy->private_data;
1401d5ac70f0Sopenharmony_ci	unsigned int min_choices = UINT_MAX;
1402d5ac70f0Sopenharmony_ci	unsigned int min_order = UINT_MAX;
1403d5ac70f0Sopenharmony_ci	for (var = 0; var <= SND_PCM_HW_PARAM_LAST_INTERVAL; ++var) {
1404d5ac70f0Sopenharmony_ci		const snd_pcm_hw_strategy_simple_t *p = &pars[var];
1405d5ac70f0Sopenharmony_ci		unsigned int choices;
1406d5ac70f0Sopenharmony_ci		if (!p->valid)
1407d5ac70f0Sopenharmony_ci			continue;
1408d5ac70f0Sopenharmony_ci		choices = snd_pcm_hw_param_count(params, var);
1409d5ac70f0Sopenharmony_ci		if (choices == 1)
1410d5ac70f0Sopenharmony_ci			continue;
1411d5ac70f0Sopenharmony_ci		assert(choices != 0);
1412d5ac70f0Sopenharmony_ci		if (p->order < min_order ||
1413d5ac70f0Sopenharmony_ci		    (p->order == min_order &&
1414d5ac70f0Sopenharmony_ci		     choices < min_choices)) {
1415d5ac70f0Sopenharmony_ci			min_order = p->order;
1416d5ac70f0Sopenharmony_ci			min_choices = choices;
1417d5ac70f0Sopenharmony_ci			best_var = var;
1418d5ac70f0Sopenharmony_ci		}
1419d5ac70f0Sopenharmony_ci	}
1420d5ac70f0Sopenharmony_ci	return best_var;
1421d5ac70f0Sopenharmony_ci}
1422d5ac70f0Sopenharmony_ci
1423d5ac70f0Sopenharmony_ciint snd_pcm_hw_strategy_simple_next_value(snd_pcm_hw_params_t *params,
1424d5ac70f0Sopenharmony_ci					  snd_pcm_hw_param_t var,
1425d5ac70f0Sopenharmony_ci					  int value, int *dir,
1426d5ac70f0Sopenharmony_ci					  snd_pcm_t *pcm,
1427d5ac70f0Sopenharmony_ci					  const snd_pcm_hw_strategy_t *strategy)
1428d5ac70f0Sopenharmony_ci{
1429d5ac70f0Sopenharmony_ci	const snd_pcm_hw_strategy_simple_t *pars = strategy->private_data;
1430d5ac70f0Sopenharmony_ci	assert(pars[var].valid);
1431d5ac70f0Sopenharmony_ci	return pars[var].next_value(params, var, value, dir, pcm, &pars[var]);
1432d5ac70f0Sopenharmony_ci}
1433d5ac70f0Sopenharmony_ci
1434d5ac70f0Sopenharmony_ci
1435d5ac70f0Sopenharmony_ciint snd_pcm_hw_strategy_simple_min_badness(const snd_pcm_hw_params_t *params,
1436d5ac70f0Sopenharmony_ci					unsigned int max_badness,
1437d5ac70f0Sopenharmony_ci					snd_pcm_t *pcm,
1438d5ac70f0Sopenharmony_ci					const snd_pcm_hw_strategy_t *strategy)
1439d5ac70f0Sopenharmony_ci{
1440d5ac70f0Sopenharmony_ci	snd_pcm_hw_param_t var;
1441d5ac70f0Sopenharmony_ci	unsigned int badness = 0;
1442d5ac70f0Sopenharmony_ci	const snd_pcm_hw_strategy_simple_t *pars = strategy->private_data;
1443d5ac70f0Sopenharmony_ci	for (var = 0; var <= SND_PCM_HW_PARAM_LAST_INTERVAL; ++var) {
1444d5ac70f0Sopenharmony_ci		unsigned int b;
1445d5ac70f0Sopenharmony_ci		if (!pars[var].valid)
1446d5ac70f0Sopenharmony_ci			continue;
1447d5ac70f0Sopenharmony_ci		b = pars[var].min_badness(params, var, pcm, &pars[var]);
1448d5ac70f0Sopenharmony_ci		if (b > max_badness || max_badness - b < badness)
1449d5ac70f0Sopenharmony_ci			return -E2BIG;
1450d5ac70f0Sopenharmony_ci		badness += b;
1451d5ac70f0Sopenharmony_ci	}
1452d5ac70f0Sopenharmony_ci	return badness;
1453d5ac70f0Sopenharmony_ci}
1454d5ac70f0Sopenharmony_ci
1455d5ac70f0Sopenharmony_ci
1456d5ac70f0Sopenharmony_civoid snd_pcm_hw_strategy_simple_near_free(snd_pcm_hw_strategy_simple_t *par)
1457d5ac70f0Sopenharmony_ci{
1458d5ac70f0Sopenharmony_ci	snd_pcm_hw_strategy_simple_near_t *p = par->private_data;
1459d5ac70f0Sopenharmony_ci	free(p);
1460d5ac70f0Sopenharmony_ci}
1461d5ac70f0Sopenharmony_ci
1462d5ac70f0Sopenharmony_ciunsigned int snd_pcm_hw_strategy_simple_near_min_badness(const snd_pcm_hw_params_t *params,
1463d5ac70f0Sopenharmony_ci						      snd_pcm_hw_param_t var,
1464d5ac70f0Sopenharmony_ci						      snd_pcm_t *pcm,
1465d5ac70f0Sopenharmony_ci						      const snd_pcm_hw_strategy_simple_t *par)
1466d5ac70f0Sopenharmony_ci{
1467d5ac70f0Sopenharmony_ci	const snd_pcm_hw_strategy_simple_near_t *p = par->private_data;
1468d5ac70f0Sopenharmony_ci	snd_pcm_hw_params_t params1 = *params;
1469d5ac70f0Sopenharmony_ci	int value = snd_pcm_hw_param_set_near(pcm, &params1, var, p->best, 0);
1470d5ac70f0Sopenharmony_ci	int diff;
1471d5ac70f0Sopenharmony_ci	assert(value >= 0);
1472d5ac70f0Sopenharmony_ci	diff = p->best - value;
1473d5ac70f0Sopenharmony_ci	if (diff < 0)
1474d5ac70f0Sopenharmony_ci		diff = -diff;
1475d5ac70f0Sopenharmony_ci	return diff * p->mul;
1476d5ac70f0Sopenharmony_ci}
1477d5ac70f0Sopenharmony_ci
1478d5ac70f0Sopenharmony_ciint snd_pcm_hw_strategy_simple_near_next_value(snd_pcm_hw_params_t *params,
1479d5ac70f0Sopenharmony_ci					       snd_pcm_hw_param_t var,
1480d5ac70f0Sopenharmony_ci					       int value, int *dir,
1481d5ac70f0Sopenharmony_ci					       snd_pcm_t *pcm,
1482d5ac70f0Sopenharmony_ci					       const snd_pcm_hw_strategy_simple_t *par)
1483d5ac70f0Sopenharmony_ci{
1484d5ac70f0Sopenharmony_ci	const snd_pcm_hw_strategy_simple_near_t *p = par->private_data;
1485d5ac70f0Sopenharmony_ci	if (value < 0) {
1486d5ac70f0Sopenharmony_ci		*dir = 0;
1487d5ac70f0Sopenharmony_ci		return snd_pcm_hw_param_set_near(pcm, params, var, p->best, dir);
1488d5ac70f0Sopenharmony_ci	} else
1489d5ac70f0Sopenharmony_ci		return snd_pcm_hw_param_set_next(pcm, params, var, p->best, 0, value, dir);
1490d5ac70f0Sopenharmony_ci}
1491d5ac70f0Sopenharmony_ci
1492d5ac70f0Sopenharmony_civoid snd_pcm_hw_strategy_simple_choices_free(snd_pcm_hw_strategy_simple_t *par)
1493d5ac70f0Sopenharmony_ci{
1494d5ac70f0Sopenharmony_ci	snd_pcm_hw_strategy_simple_choices_t *p = par->private_data;
1495d5ac70f0Sopenharmony_ci//	free(p->choices);
1496d5ac70f0Sopenharmony_ci	free(p);
1497d5ac70f0Sopenharmony_ci}
1498d5ac70f0Sopenharmony_ci
1499d5ac70f0Sopenharmony_ciunsigned int snd_pcm_hw_strategy_simple_choices_min_badness(const snd_pcm_hw_params_t *params,
1500d5ac70f0Sopenharmony_ci							 snd_pcm_hw_param_t var,
1501d5ac70f0Sopenharmony_ci							 snd_pcm_t *pcm,
1502d5ac70f0Sopenharmony_ci							 const snd_pcm_hw_strategy_simple_t *par)
1503d5ac70f0Sopenharmony_ci{
1504d5ac70f0Sopenharmony_ci	const snd_pcm_hw_strategy_simple_choices_t *p = par->private_data;
1505d5ac70f0Sopenharmony_ci	unsigned int k;
1506d5ac70f0Sopenharmony_ci	for (k = 0; k < p->count; ++k) {
1507d5ac70f0Sopenharmony_ci		if (snd_pcm_hw_param_set(pcm, (snd_pcm_hw_params_t *) params, SND_TEST, var, p->choices[k].value, 0))
1508d5ac70f0Sopenharmony_ci			return p->choices[k].badness;
1509d5ac70f0Sopenharmony_ci	}
1510d5ac70f0Sopenharmony_ci	assert(0);
1511d5ac70f0Sopenharmony_ci	return UINT_MAX;
1512d5ac70f0Sopenharmony_ci}
1513d5ac70f0Sopenharmony_ci
1514d5ac70f0Sopenharmony_ciint snd_pcm_hw_strategy_simple_choices_next_value(snd_pcm_hw_params_t *params,
1515d5ac70f0Sopenharmony_ci						  snd_pcm_hw_param_t var,
1516d5ac70f0Sopenharmony_ci						  int value, int *dir,
1517d5ac70f0Sopenharmony_ci						  snd_pcm_t *pcm,
1518d5ac70f0Sopenharmony_ci						  const snd_pcm_hw_strategy_simple_t *par)
1519d5ac70f0Sopenharmony_ci{
1520d5ac70f0Sopenharmony_ci	const snd_pcm_hw_strategy_simple_choices_t *p = par->private_data;
1521d5ac70f0Sopenharmony_ci	unsigned int k = 0;
1522d5ac70f0Sopenharmony_ci	if (value >= 0) {
1523d5ac70f0Sopenharmony_ci		for (; k < p->count; ++k) {
1524d5ac70f0Sopenharmony_ci			if (p->choices[k].value == (unsigned int) value) {
1525d5ac70f0Sopenharmony_ci				k++;
1526d5ac70f0Sopenharmony_ci				break;
1527d5ac70f0Sopenharmony_ci			}
1528d5ac70f0Sopenharmony_ci		}
1529d5ac70f0Sopenharmony_ci	}
1530d5ac70f0Sopenharmony_ci	for (; k < p->count; ++k) {
1531d5ac70f0Sopenharmony_ci		unsigned int v = p->choices[k].value;
1532d5ac70f0Sopenharmony_ci		int err = snd_pcm_hw_param_set(pcm, params, SND_TRY, var, v, 0);
1533d5ac70f0Sopenharmony_ci		if (err < 0)
1534d5ac70f0Sopenharmony_ci			continue;
1535d5ac70f0Sopenharmony_ci		*dir = 0;
1536d5ac70f0Sopenharmony_ci		return v;
1537d5ac70f0Sopenharmony_ci	}
1538d5ac70f0Sopenharmony_ci	return -1;
1539d5ac70f0Sopenharmony_ci}
1540d5ac70f0Sopenharmony_ci
1541d5ac70f0Sopenharmony_civoid snd_pcm_hw_strategy_free(snd_pcm_hw_strategy_t *strategy)
1542d5ac70f0Sopenharmony_ci{
1543d5ac70f0Sopenharmony_ci	if (strategy->free)
1544d5ac70f0Sopenharmony_ci		strategy->free(strategy);
1545d5ac70f0Sopenharmony_ci	free(strategy);
1546d5ac70f0Sopenharmony_ci}
1547d5ac70f0Sopenharmony_ci
1548d5ac70f0Sopenharmony_ciint snd_pcm_hw_strategy_simple(snd_pcm_hw_strategy_t **strategyp,
1549d5ac70f0Sopenharmony_ci			    unsigned int badness_min,
1550d5ac70f0Sopenharmony_ci			    unsigned int badness_max)
1551d5ac70f0Sopenharmony_ci{
1552d5ac70f0Sopenharmony_ci	snd_pcm_hw_strategy_simple_t *data;
1553d5ac70f0Sopenharmony_ci	snd_pcm_hw_strategy_t *s;
1554d5ac70f0Sopenharmony_ci	assert(strategyp);
1555d5ac70f0Sopenharmony_ci	data = calloc(SND_PCM_HW_PARAM_LAST_INTERVAL + 1, sizeof(*data));
1556d5ac70f0Sopenharmony_ci	if (!data)
1557d5ac70f0Sopenharmony_ci		return -ENOMEM;
1558d5ac70f0Sopenharmony_ci	s = calloc(1, sizeof(*s));
1559d5ac70f0Sopenharmony_ci	if (!s) {
1560d5ac70f0Sopenharmony_ci		free(data);
1561d5ac70f0Sopenharmony_ci		return -ENOMEM;
1562d5ac70f0Sopenharmony_ci	}
1563d5ac70f0Sopenharmony_ci	s->choose_param = snd_pcm_hw_strategy_simple_choose_param;
1564d5ac70f0Sopenharmony_ci	s->next_value = snd_pcm_hw_strategy_simple_next_value;
1565d5ac70f0Sopenharmony_ci	s->min_badness = snd_pcm_hw_strategy_simple_min_badness;
1566d5ac70f0Sopenharmony_ci	s->badness_min = badness_min;
1567d5ac70f0Sopenharmony_ci	s->badness_max = badness_max;
1568d5ac70f0Sopenharmony_ci	s->private_data = data;
1569d5ac70f0Sopenharmony_ci	s->free = snd_pcm_hw_strategy_simple_free;
1570d5ac70f0Sopenharmony_ci	*strategyp = s;
1571d5ac70f0Sopenharmony_ci	return 0;
1572d5ac70f0Sopenharmony_ci}
1573d5ac70f0Sopenharmony_ci
1574d5ac70f0Sopenharmony_ciint snd_pcm_hw_strategy_simple_near(snd_pcm_hw_strategy_t *strategy,
1575d5ac70f0Sopenharmony_ci				 int order,
1576d5ac70f0Sopenharmony_ci				 snd_pcm_hw_param_t var,
1577d5ac70f0Sopenharmony_ci				 unsigned int best,
1578d5ac70f0Sopenharmony_ci				 unsigned int mul)
1579d5ac70f0Sopenharmony_ci{
1580d5ac70f0Sopenharmony_ci	snd_pcm_hw_strategy_simple_t *s = strategy->private_data;
1581d5ac70f0Sopenharmony_ci	snd_pcm_hw_strategy_simple_near_t *data;
1582d5ac70f0Sopenharmony_ci	assert(strategy);
1583d5ac70f0Sopenharmony_ci	assert(var <= SND_PCM_HW_PARAM_LAST_INTERVAL);
1584d5ac70f0Sopenharmony_ci	assert(!s->valid);
1585d5ac70f0Sopenharmony_ci	data = calloc(1, sizeof(*data));
1586d5ac70f0Sopenharmony_ci	if (!data)
1587d5ac70f0Sopenharmony_ci		return -ENOMEM;
1588d5ac70f0Sopenharmony_ci	data->best = best;
1589d5ac70f0Sopenharmony_ci	data->mul = mul;
1590d5ac70f0Sopenharmony_ci	s += var;
1591d5ac70f0Sopenharmony_ci	s->order = order;
1592d5ac70f0Sopenharmony_ci	s->valid = 1;
1593d5ac70f0Sopenharmony_ci	s->next_value = snd_pcm_hw_strategy_simple_near_next_value;
1594d5ac70f0Sopenharmony_ci	s->min_badness = snd_pcm_hw_strategy_simple_near_min_badness;
1595d5ac70f0Sopenharmony_ci	s->private_data = data;
1596d5ac70f0Sopenharmony_ci	s->free = snd_pcm_hw_strategy_simple_near_free;
1597d5ac70f0Sopenharmony_ci	return 0;
1598d5ac70f0Sopenharmony_ci}
1599d5ac70f0Sopenharmony_ci
1600d5ac70f0Sopenharmony_ciint snd_pcm_hw_strategy_simple_choices(snd_pcm_hw_strategy_t *strategy,
1601d5ac70f0Sopenharmony_ci				    int order,
1602d5ac70f0Sopenharmony_ci				    snd_pcm_hw_param_t var,
1603d5ac70f0Sopenharmony_ci				    unsigned int count,
1604d5ac70f0Sopenharmony_ci				    snd_pcm_hw_strategy_simple_choices_list_t *choices)
1605d5ac70f0Sopenharmony_ci{
1606d5ac70f0Sopenharmony_ci	snd_pcm_hw_strategy_simple_t *s = strategy->private_data;
1607d5ac70f0Sopenharmony_ci	snd_pcm_hw_strategy_simple_choices_t *data;
1608d5ac70f0Sopenharmony_ci	assert(strategy);
1609d5ac70f0Sopenharmony_ci	assert(var <= SND_PCM_HW_PARAM_LAST_INTERVAL);
1610d5ac70f0Sopenharmony_ci	assert(!s->valid);
1611d5ac70f0Sopenharmony_ci	data = calloc(1, sizeof(*data));
1612d5ac70f0Sopenharmony_ci	if (!data)
1613d5ac70f0Sopenharmony_ci		return -ENOMEM;
1614d5ac70f0Sopenharmony_ci	data->count = count;
1615d5ac70f0Sopenharmony_ci	data->choices = choices;
1616d5ac70f0Sopenharmony_ci	s += var;
1617d5ac70f0Sopenharmony_ci	s->valid = 1;
1618d5ac70f0Sopenharmony_ci	s->order = order;
1619d5ac70f0Sopenharmony_ci	s->next_value = snd_pcm_hw_strategy_simple_choices_next_value;
1620d5ac70f0Sopenharmony_ci	s->min_badness = snd_pcm_hw_strategy_simple_choices_min_badness;
1621d5ac70f0Sopenharmony_ci	s->private_data = data;
1622d5ac70f0Sopenharmony_ci	s->free = snd_pcm_hw_strategy_simple_choices_free;
1623d5ac70f0Sopenharmony_ci	return 0;
1624d5ac70f0Sopenharmony_ci}
1625d5ac70f0Sopenharmony_ci
1626d5ac70f0Sopenharmony_ciint snd_pcm_hw_params_try_explain_failure1(snd_pcm_t *pcm,
1627d5ac70f0Sopenharmony_ci					   snd_pcm_hw_params_t *fail,
1628d5ac70f0Sopenharmony_ci					   snd_pcm_hw_params_t *success,
1629d5ac70f0Sopenharmony_ci					   unsigned int depth,
1630d5ac70f0Sopenharmony_ci					   snd_output_t *out)
1631d5ac70f0Sopenharmony_ci{
1632d5ac70f0Sopenharmony_ci	snd_pcm_hw_param_t var;
1633d5ac70f0Sopenharmony_ci	snd_pcm_hw_params_t i;
1634d5ac70f0Sopenharmony_ci	if (depth < 1)
1635d5ac70f0Sopenharmony_ci		return -ENOENT;
1636d5ac70f0Sopenharmony_ci	for (var = 0; var <= SND_PCM_HW_PARAM_LAST_INTERVAL; var++) {
1637d5ac70f0Sopenharmony_ci		int err;
1638d5ac70f0Sopenharmony_ci		i = *success;
1639d5ac70f0Sopenharmony_ci		_snd_pcm_hw_param_copy(&i, var, fail);
1640d5ac70f0Sopenharmony_ci		err = snd_pcm_hw_refine(pcm, &i);
1641d5ac70f0Sopenharmony_ci		if (err == 0 &&
1642d5ac70f0Sopenharmony_ci		    snd_pcm_hw_params_try_explain_failure1(pcm, fail, &i, depth - 1, out) < 0)
1643d5ac70f0Sopenharmony_ci			continue;
1644d5ac70f0Sopenharmony_ci		snd_output_printf(out, "%s: ", snd_pcm_hw_param_name(var));
1645d5ac70f0Sopenharmony_ci		snd_pcm_hw_param_dump(fail, var, out);
1646d5ac70f0Sopenharmony_ci		snd_output_putc(out, '\n');
1647d5ac70f0Sopenharmony_ci		return 0;
1648d5ac70f0Sopenharmony_ci	}
1649d5ac70f0Sopenharmony_ci	return -ENOENT;
1650d5ac70f0Sopenharmony_ci}
1651d5ac70f0Sopenharmony_ci
1652d5ac70f0Sopenharmony_ciint snd_pcm_hw_params_try_explain_failure(snd_pcm_t *pcm,
1653d5ac70f0Sopenharmony_ci					  snd_pcm_hw_params_t *fail,
1654d5ac70f0Sopenharmony_ci					  snd_pcm_hw_params_t *success,
1655d5ac70f0Sopenharmony_ci					  unsigned int depth,
1656d5ac70f0Sopenharmony_ci					  snd_output_t *out)
1657d5ac70f0Sopenharmony_ci{
1658d5ac70f0Sopenharmony_ci	snd_pcm_hw_params_t i, any;
1659d5ac70f0Sopenharmony_ci	int err;
1660d5ac70f0Sopenharmony_ci	snd_pcm_hw_param_t var;
1661d5ac70f0Sopenharmony_ci	int done = 0;
1662d5ac70f0Sopenharmony_ci	assert(pcm && fail);
1663d5ac70f0Sopenharmony_ci	for (var = 0; var <= SND_PCM_HW_PARAM_LAST_INTERVAL; var++) {
1664d5ac70f0Sopenharmony_ci		if (!snd_pcm_hw_param_empty(fail, var))
1665d5ac70f0Sopenharmony_ci			continue;
1666d5ac70f0Sopenharmony_ci		snd_output_printf(out, "%s is empty\n", snd_pcm_hw_param_name(var));
1667d5ac70f0Sopenharmony_ci		done = 1;
1668d5ac70f0Sopenharmony_ci	}
1669d5ac70f0Sopenharmony_ci	if (done)
1670d5ac70f0Sopenharmony_ci		return 0;
1671d5ac70f0Sopenharmony_ci	i = *fail;
1672d5ac70f0Sopenharmony_ci	err = snd_pcm_hw_refine(pcm, &i);
1673d5ac70f0Sopenharmony_ci	if (err == 0) {
1674d5ac70f0Sopenharmony_ci		snd_output_printf(out, "Configuration is virtually correct\n");
1675d5ac70f0Sopenharmony_ci		return 0;
1676d5ac70f0Sopenharmony_ci	}
1677d5ac70f0Sopenharmony_ci	if (!success) {
1678d5ac70f0Sopenharmony_ci		snd_pcm_hw_params_any(pcm, &any);
1679d5ac70f0Sopenharmony_ci		success = &any;
1680d5ac70f0Sopenharmony_ci	}
1681d5ac70f0Sopenharmony_ci	return snd_pcm_hw_params_try_explain_failure1(pcm, fail, success, depth, out);
1682d5ac70f0Sopenharmony_ci}
1683d5ac70f0Sopenharmony_ci
1684d5ac70f0Sopenharmony_ci#endif
1685d5ac70f0Sopenharmony_ci
1686d5ac70f0Sopenharmony_citypedef struct _snd_pcm_hw_rule snd_pcm_hw_rule_t;
1687d5ac70f0Sopenharmony_ci
1688d5ac70f0Sopenharmony_citypedef int (*snd_pcm_hw_rule_func_t)(snd_pcm_hw_params_t *params,
1689d5ac70f0Sopenharmony_ci				      const snd_pcm_hw_rule_t *rule);
1690d5ac70f0Sopenharmony_ci
1691d5ac70f0Sopenharmony_cistruct _snd_pcm_hw_rule {
1692d5ac70f0Sopenharmony_ci	int var;
1693d5ac70f0Sopenharmony_ci	snd_pcm_hw_rule_func_t func;
1694d5ac70f0Sopenharmony_ci	int deps[4];
1695d5ac70f0Sopenharmony_ci	void *private_data;
1696d5ac70f0Sopenharmony_ci};
1697d5ac70f0Sopenharmony_ci
1698d5ac70f0Sopenharmony_cistatic int snd_pcm_hw_rule_mul(snd_pcm_hw_params_t *params,
1699d5ac70f0Sopenharmony_ci			       const snd_pcm_hw_rule_t *rule)
1700d5ac70f0Sopenharmony_ci{
1701d5ac70f0Sopenharmony_ci	snd_interval_t t;
1702d5ac70f0Sopenharmony_ci	snd_interval_mul(hw_param_interval_c(params, rule->deps[0]),
1703d5ac70f0Sopenharmony_ci		     hw_param_interval_c(params, rule->deps[1]), &t);
1704d5ac70f0Sopenharmony_ci	return snd_interval_refine(hw_param_interval(params, rule->var), &t);
1705d5ac70f0Sopenharmony_ci}
1706d5ac70f0Sopenharmony_ci
1707d5ac70f0Sopenharmony_cistatic int snd_pcm_hw_rule_div(snd_pcm_hw_params_t *params,
1708d5ac70f0Sopenharmony_ci			const snd_pcm_hw_rule_t *rule)
1709d5ac70f0Sopenharmony_ci{
1710d5ac70f0Sopenharmony_ci	snd_interval_t t;
1711d5ac70f0Sopenharmony_ci	snd_interval_div(hw_param_interval_c(params, rule->deps[0]),
1712d5ac70f0Sopenharmony_ci		     hw_param_interval_c(params, rule->deps[1]), &t);
1713d5ac70f0Sopenharmony_ci	return snd_interval_refine(hw_param_interval(params, rule->var), &t);
1714d5ac70f0Sopenharmony_ci}
1715d5ac70f0Sopenharmony_ci
1716d5ac70f0Sopenharmony_cistatic int snd_pcm_hw_rule_muldivk(snd_pcm_hw_params_t *params,
1717d5ac70f0Sopenharmony_ci				   const snd_pcm_hw_rule_t *rule)
1718d5ac70f0Sopenharmony_ci{
1719d5ac70f0Sopenharmony_ci	snd_interval_t t;
1720d5ac70f0Sopenharmony_ci	snd_interval_muldivk(hw_param_interval_c(params, rule->deps[0]),
1721d5ac70f0Sopenharmony_ci			 hw_param_interval_c(params, rule->deps[1]),
1722d5ac70f0Sopenharmony_ci			 (unsigned long) rule->private_data, &t);
1723d5ac70f0Sopenharmony_ci	return snd_interval_refine(hw_param_interval(params, rule->var), &t);
1724d5ac70f0Sopenharmony_ci}
1725d5ac70f0Sopenharmony_ci
1726d5ac70f0Sopenharmony_cistatic int snd_pcm_hw_rule_mulkdiv(snd_pcm_hw_params_t *params,
1727d5ac70f0Sopenharmony_ci				   const snd_pcm_hw_rule_t *rule)
1728d5ac70f0Sopenharmony_ci{
1729d5ac70f0Sopenharmony_ci	snd_interval_t t;
1730d5ac70f0Sopenharmony_ci	snd_interval_mulkdiv(hw_param_interval_c(params, rule->deps[0]),
1731d5ac70f0Sopenharmony_ci			 (unsigned long) rule->private_data,
1732d5ac70f0Sopenharmony_ci			 hw_param_interval_c(params, rule->deps[1]), &t);
1733d5ac70f0Sopenharmony_ci	return snd_interval_refine(hw_param_interval(params, rule->var), &t);
1734d5ac70f0Sopenharmony_ci}
1735d5ac70f0Sopenharmony_ci
1736d5ac70f0Sopenharmony_cistatic int snd_pcm_hw_rule_format(snd_pcm_hw_params_t *params,
1737d5ac70f0Sopenharmony_ci				  const snd_pcm_hw_rule_t *rule)
1738d5ac70f0Sopenharmony_ci{
1739d5ac70f0Sopenharmony_ci	int changed = 0;
1740d5ac70f0Sopenharmony_ci	snd_pcm_format_t k;
1741d5ac70f0Sopenharmony_ci	snd_mask_t *mask = hw_param_mask(params, rule->var);
1742d5ac70f0Sopenharmony_ci	snd_interval_t *i = hw_param_interval(params, rule->deps[0]);
1743d5ac70f0Sopenharmony_ci	for (k = 0; k <= SND_PCM_FORMAT_LAST; k++) {
1744d5ac70f0Sopenharmony_ci		int bits;
1745d5ac70f0Sopenharmony_ci		if (!snd_pcm_format_mask_test(mask, k))
1746d5ac70f0Sopenharmony_ci			continue;
1747d5ac70f0Sopenharmony_ci		bits = snd_pcm_format_physical_width(k);
1748d5ac70f0Sopenharmony_ci		if (bits < 0)
1749d5ac70f0Sopenharmony_ci			continue;
1750d5ac70f0Sopenharmony_ci		if (!snd_interval_test(i, (unsigned int) bits)) {
1751d5ac70f0Sopenharmony_ci			snd_pcm_format_mask_reset(mask, k);
1752d5ac70f0Sopenharmony_ci			if (snd_mask_empty(mask))
1753d5ac70f0Sopenharmony_ci				return -EINVAL;
1754d5ac70f0Sopenharmony_ci			changed = 1;
1755d5ac70f0Sopenharmony_ci		}
1756d5ac70f0Sopenharmony_ci	}
1757d5ac70f0Sopenharmony_ci	return changed;
1758d5ac70f0Sopenharmony_ci}
1759d5ac70f0Sopenharmony_ci
1760d5ac70f0Sopenharmony_ci
1761d5ac70f0Sopenharmony_cistatic int snd_pcm_hw_rule_sample_bits(snd_pcm_hw_params_t *params,
1762d5ac70f0Sopenharmony_ci				       const snd_pcm_hw_rule_t *rule)
1763d5ac70f0Sopenharmony_ci{
1764d5ac70f0Sopenharmony_ci	unsigned int min, max;
1765d5ac70f0Sopenharmony_ci	snd_pcm_format_t k;
1766d5ac70f0Sopenharmony_ci	snd_interval_t *i = hw_param_interval(params, rule->var);
1767d5ac70f0Sopenharmony_ci	snd_mask_t *mask = hw_param_mask(params, rule->deps[0]);
1768d5ac70f0Sopenharmony_ci	int c, changed = 0;
1769d5ac70f0Sopenharmony_ci	min = UINT_MAX;
1770d5ac70f0Sopenharmony_ci	max = 0;
1771d5ac70f0Sopenharmony_ci	for (k = 0; k <= SND_PCM_FORMAT_LAST; k++) {
1772d5ac70f0Sopenharmony_ci		int bits;
1773d5ac70f0Sopenharmony_ci		if (!snd_pcm_format_mask_test(mask, k))
1774d5ac70f0Sopenharmony_ci			continue;
1775d5ac70f0Sopenharmony_ci		bits = snd_pcm_format_physical_width(k);
1776d5ac70f0Sopenharmony_ci		if (bits < 0)
1777d5ac70f0Sopenharmony_ci			continue;
1778d5ac70f0Sopenharmony_ci		if (min > (unsigned)bits)
1779d5ac70f0Sopenharmony_ci			min = bits;
1780d5ac70f0Sopenharmony_ci		if (max < (unsigned)bits)
1781d5ac70f0Sopenharmony_ci			max = bits;
1782d5ac70f0Sopenharmony_ci	}
1783d5ac70f0Sopenharmony_ci	c = snd_interval_refine_min(i, min, 0);
1784d5ac70f0Sopenharmony_ci	if (c < 0)
1785d5ac70f0Sopenharmony_ci		return c;
1786d5ac70f0Sopenharmony_ci	if (c)
1787d5ac70f0Sopenharmony_ci		changed = 1;
1788d5ac70f0Sopenharmony_ci	c = snd_interval_refine_max(i, max, 0);
1789d5ac70f0Sopenharmony_ci	if (c < 0)
1790d5ac70f0Sopenharmony_ci		return c;
1791d5ac70f0Sopenharmony_ci	if (c)
1792d5ac70f0Sopenharmony_ci		changed = 1;
1793d5ac70f0Sopenharmony_ci	return changed;
1794d5ac70f0Sopenharmony_ci}
1795d5ac70f0Sopenharmony_ci
1796d5ac70f0Sopenharmony_cistatic const snd_pcm_hw_rule_t refine_rules[] = {
1797d5ac70f0Sopenharmony_ci	{
1798d5ac70f0Sopenharmony_ci		.var = SND_PCM_HW_PARAM_FORMAT,
1799d5ac70f0Sopenharmony_ci		.func = snd_pcm_hw_rule_format,
1800d5ac70f0Sopenharmony_ci		.deps = { SND_PCM_HW_PARAM_SAMPLE_BITS, -1 },
1801d5ac70f0Sopenharmony_ci		.private_data = 0,
1802d5ac70f0Sopenharmony_ci	},
1803d5ac70f0Sopenharmony_ci	{
1804d5ac70f0Sopenharmony_ci		.var = SND_PCM_HW_PARAM_SAMPLE_BITS,
1805d5ac70f0Sopenharmony_ci		.func = snd_pcm_hw_rule_sample_bits,
1806d5ac70f0Sopenharmony_ci		.deps = { SND_PCM_HW_PARAM_FORMAT,
1807d5ac70f0Sopenharmony_ci			SND_PCM_HW_PARAM_SAMPLE_BITS, -1 },
1808d5ac70f0Sopenharmony_ci		.private_data = 0,
1809d5ac70f0Sopenharmony_ci	},
1810d5ac70f0Sopenharmony_ci	{
1811d5ac70f0Sopenharmony_ci		.var = SND_PCM_HW_PARAM_SAMPLE_BITS,
1812d5ac70f0Sopenharmony_ci		.func = snd_pcm_hw_rule_div,
1813d5ac70f0Sopenharmony_ci		.deps = { SND_PCM_HW_PARAM_FRAME_BITS,
1814d5ac70f0Sopenharmony_ci			SND_PCM_HW_PARAM_CHANNELS, -1 },
1815d5ac70f0Sopenharmony_ci		.private_data = 0,
1816d5ac70f0Sopenharmony_ci	},
1817d5ac70f0Sopenharmony_ci	{
1818d5ac70f0Sopenharmony_ci		.var = SND_PCM_HW_PARAM_FRAME_BITS,
1819d5ac70f0Sopenharmony_ci		.func = snd_pcm_hw_rule_mul,
1820d5ac70f0Sopenharmony_ci		.deps = { SND_PCM_HW_PARAM_SAMPLE_BITS,
1821d5ac70f0Sopenharmony_ci			SND_PCM_HW_PARAM_CHANNELS, -1 },
1822d5ac70f0Sopenharmony_ci		.private_data = 0,
1823d5ac70f0Sopenharmony_ci	},
1824d5ac70f0Sopenharmony_ci	{
1825d5ac70f0Sopenharmony_ci		.var = SND_PCM_HW_PARAM_FRAME_BITS,
1826d5ac70f0Sopenharmony_ci		.func = snd_pcm_hw_rule_mulkdiv,
1827d5ac70f0Sopenharmony_ci		.deps = { SND_PCM_HW_PARAM_PERIOD_BYTES,
1828d5ac70f0Sopenharmony_ci			SND_PCM_HW_PARAM_PERIOD_SIZE, -1 },
1829d5ac70f0Sopenharmony_ci		.private_data = (void*) 8,
1830d5ac70f0Sopenharmony_ci	},
1831d5ac70f0Sopenharmony_ci	{
1832d5ac70f0Sopenharmony_ci		.var = SND_PCM_HW_PARAM_FRAME_BITS,
1833d5ac70f0Sopenharmony_ci		.func = snd_pcm_hw_rule_mulkdiv,
1834d5ac70f0Sopenharmony_ci		.deps = { SND_PCM_HW_PARAM_BUFFER_BYTES,
1835d5ac70f0Sopenharmony_ci			SND_PCM_HW_PARAM_BUFFER_SIZE, -1 },
1836d5ac70f0Sopenharmony_ci		.private_data = (void*) 8,
1837d5ac70f0Sopenharmony_ci	},
1838d5ac70f0Sopenharmony_ci	{
1839d5ac70f0Sopenharmony_ci		.var = SND_PCM_HW_PARAM_CHANNELS,
1840d5ac70f0Sopenharmony_ci		.func = snd_pcm_hw_rule_div,
1841d5ac70f0Sopenharmony_ci		.deps = { SND_PCM_HW_PARAM_FRAME_BITS,
1842d5ac70f0Sopenharmony_ci			SND_PCM_HW_PARAM_SAMPLE_BITS, -1 },
1843d5ac70f0Sopenharmony_ci		.private_data = 0,
1844d5ac70f0Sopenharmony_ci	},
1845d5ac70f0Sopenharmony_ci	{
1846d5ac70f0Sopenharmony_ci		.var = SND_PCM_HW_PARAM_RATE,
1847d5ac70f0Sopenharmony_ci		.func = snd_pcm_hw_rule_mulkdiv,
1848d5ac70f0Sopenharmony_ci		.deps = { SND_PCM_HW_PARAM_PERIOD_SIZE,
1849d5ac70f0Sopenharmony_ci			SND_PCM_HW_PARAM_PERIOD_TIME, -1 },
1850d5ac70f0Sopenharmony_ci		.private_data = (void*) 1000000,
1851d5ac70f0Sopenharmony_ci	},
1852d5ac70f0Sopenharmony_ci	{
1853d5ac70f0Sopenharmony_ci		.var = SND_PCM_HW_PARAM_RATE,
1854d5ac70f0Sopenharmony_ci		.func = snd_pcm_hw_rule_mulkdiv,
1855d5ac70f0Sopenharmony_ci		.deps = { SND_PCM_HW_PARAM_BUFFER_SIZE,
1856d5ac70f0Sopenharmony_ci			SND_PCM_HW_PARAM_BUFFER_TIME, -1 },
1857d5ac70f0Sopenharmony_ci		.private_data = (void*) 1000000,
1858d5ac70f0Sopenharmony_ci	},
1859d5ac70f0Sopenharmony_ci	{
1860d5ac70f0Sopenharmony_ci		.var = SND_PCM_HW_PARAM_PERIODS,
1861d5ac70f0Sopenharmony_ci		.func = snd_pcm_hw_rule_div,
1862d5ac70f0Sopenharmony_ci		.deps = { SND_PCM_HW_PARAM_BUFFER_SIZE,
1863d5ac70f0Sopenharmony_ci			SND_PCM_HW_PARAM_PERIOD_SIZE, -1 },
1864d5ac70f0Sopenharmony_ci		.private_data = 0,
1865d5ac70f0Sopenharmony_ci	},
1866d5ac70f0Sopenharmony_ci	{
1867d5ac70f0Sopenharmony_ci		.var = SND_PCM_HW_PARAM_PERIOD_SIZE,
1868d5ac70f0Sopenharmony_ci		.func = snd_pcm_hw_rule_div,
1869d5ac70f0Sopenharmony_ci		.deps = { SND_PCM_HW_PARAM_BUFFER_SIZE,
1870d5ac70f0Sopenharmony_ci			SND_PCM_HW_PARAM_PERIODS, -1 },
1871d5ac70f0Sopenharmony_ci		.private_data = 0,
1872d5ac70f0Sopenharmony_ci	},
1873d5ac70f0Sopenharmony_ci	{
1874d5ac70f0Sopenharmony_ci		.var = SND_PCM_HW_PARAM_PERIOD_SIZE,
1875d5ac70f0Sopenharmony_ci		.func = snd_pcm_hw_rule_mulkdiv,
1876d5ac70f0Sopenharmony_ci		.deps = { SND_PCM_HW_PARAM_PERIOD_BYTES,
1877d5ac70f0Sopenharmony_ci			SND_PCM_HW_PARAM_FRAME_BITS, -1 },
1878d5ac70f0Sopenharmony_ci		.private_data = (void*) 8,
1879d5ac70f0Sopenharmony_ci	},
1880d5ac70f0Sopenharmony_ci	{
1881d5ac70f0Sopenharmony_ci		.var = SND_PCM_HW_PARAM_PERIOD_SIZE,
1882d5ac70f0Sopenharmony_ci		.func = snd_pcm_hw_rule_muldivk,
1883d5ac70f0Sopenharmony_ci		.deps = { SND_PCM_HW_PARAM_PERIOD_TIME,
1884d5ac70f0Sopenharmony_ci			SND_PCM_HW_PARAM_RATE, -1 },
1885d5ac70f0Sopenharmony_ci		.private_data = (void*) 1000000,
1886d5ac70f0Sopenharmony_ci	},
1887d5ac70f0Sopenharmony_ci	{
1888d5ac70f0Sopenharmony_ci		.var = SND_PCM_HW_PARAM_BUFFER_SIZE,
1889d5ac70f0Sopenharmony_ci		.func = snd_pcm_hw_rule_mul,
1890d5ac70f0Sopenharmony_ci		.deps = { SND_PCM_HW_PARAM_PERIOD_SIZE,
1891d5ac70f0Sopenharmony_ci			SND_PCM_HW_PARAM_PERIODS, -1 },
1892d5ac70f0Sopenharmony_ci		.private_data = 0,
1893d5ac70f0Sopenharmony_ci	},
1894d5ac70f0Sopenharmony_ci	{
1895d5ac70f0Sopenharmony_ci		.var = SND_PCM_HW_PARAM_BUFFER_SIZE,
1896d5ac70f0Sopenharmony_ci		.func = snd_pcm_hw_rule_mulkdiv,
1897d5ac70f0Sopenharmony_ci		.deps = { SND_PCM_HW_PARAM_BUFFER_BYTES,
1898d5ac70f0Sopenharmony_ci			SND_PCM_HW_PARAM_FRAME_BITS, -1 },
1899d5ac70f0Sopenharmony_ci		.private_data = (void*) 8,
1900d5ac70f0Sopenharmony_ci	},
1901d5ac70f0Sopenharmony_ci	{
1902d5ac70f0Sopenharmony_ci		.var = SND_PCM_HW_PARAM_BUFFER_SIZE,
1903d5ac70f0Sopenharmony_ci		.func = snd_pcm_hw_rule_muldivk,
1904d5ac70f0Sopenharmony_ci		.deps = { SND_PCM_HW_PARAM_BUFFER_TIME,
1905d5ac70f0Sopenharmony_ci			SND_PCM_HW_PARAM_RATE, -1 },
1906d5ac70f0Sopenharmony_ci		.private_data = (void*) 1000000,
1907d5ac70f0Sopenharmony_ci	},
1908d5ac70f0Sopenharmony_ci	{
1909d5ac70f0Sopenharmony_ci		.var = SND_PCM_HW_PARAM_PERIOD_BYTES,
1910d5ac70f0Sopenharmony_ci		.func = snd_pcm_hw_rule_muldivk,
1911d5ac70f0Sopenharmony_ci		.deps = { SND_PCM_HW_PARAM_PERIOD_SIZE,
1912d5ac70f0Sopenharmony_ci			SND_PCM_HW_PARAM_FRAME_BITS, -1 },
1913d5ac70f0Sopenharmony_ci		.private_data = (void*) 8,
1914d5ac70f0Sopenharmony_ci	},
1915d5ac70f0Sopenharmony_ci	{
1916d5ac70f0Sopenharmony_ci		.var = SND_PCM_HW_PARAM_BUFFER_BYTES,
1917d5ac70f0Sopenharmony_ci		.func = snd_pcm_hw_rule_muldivk,
1918d5ac70f0Sopenharmony_ci		.deps = { SND_PCM_HW_PARAM_BUFFER_SIZE,
1919d5ac70f0Sopenharmony_ci			SND_PCM_HW_PARAM_FRAME_BITS, -1 },
1920d5ac70f0Sopenharmony_ci		.private_data = (void*) 8,
1921d5ac70f0Sopenharmony_ci	},
1922d5ac70f0Sopenharmony_ci	{
1923d5ac70f0Sopenharmony_ci		.var = SND_PCM_HW_PARAM_PERIOD_TIME,
1924d5ac70f0Sopenharmony_ci		.func = snd_pcm_hw_rule_mulkdiv,
1925d5ac70f0Sopenharmony_ci		.deps = { SND_PCM_HW_PARAM_PERIOD_SIZE,
1926d5ac70f0Sopenharmony_ci			SND_PCM_HW_PARAM_RATE, -1 },
1927d5ac70f0Sopenharmony_ci		.private_data = (void*) 1000000,
1928d5ac70f0Sopenharmony_ci	},
1929d5ac70f0Sopenharmony_ci	{
1930d5ac70f0Sopenharmony_ci		.var = SND_PCM_HW_PARAM_BUFFER_TIME,
1931d5ac70f0Sopenharmony_ci		.func = snd_pcm_hw_rule_mulkdiv,
1932d5ac70f0Sopenharmony_ci		.deps = { SND_PCM_HW_PARAM_BUFFER_SIZE,
1933d5ac70f0Sopenharmony_ci			SND_PCM_HW_PARAM_RATE, -1 },
1934d5ac70f0Sopenharmony_ci		.private_data = (void*) 1000000,
1935d5ac70f0Sopenharmony_ci	},
1936d5ac70f0Sopenharmony_ci};
1937d5ac70f0Sopenharmony_ci
1938d5ac70f0Sopenharmony_ci#define RULES (sizeof(refine_rules) / sizeof(refine_rules[0]))
1939d5ac70f0Sopenharmony_ci#define PCM_BIT(x) \
1940d5ac70f0Sopenharmony_ci	(1U << ((x) < 32 ? (x) : ((x) - 32)))
1941d5ac70f0Sopenharmony_ci
1942d5ac70f0Sopenharmony_cistatic const snd_mask_t refine_masks[SND_PCM_HW_PARAM_LAST_MASK - SND_PCM_HW_PARAM_FIRST_MASK + 1] = {
1943d5ac70f0Sopenharmony_ci	[SND_PCM_HW_PARAM_ACCESS - SND_PCM_HW_PARAM_FIRST_MASK] = {
1944d5ac70f0Sopenharmony_ci		.bits = {
1945d5ac70f0Sopenharmony_ci			PCM_BIT(SNDRV_PCM_ACCESS_MMAP_INTERLEAVED) |
1946d5ac70f0Sopenharmony_ci			PCM_BIT(SNDRV_PCM_ACCESS_MMAP_NONINTERLEAVED) |
1947d5ac70f0Sopenharmony_ci			PCM_BIT(SNDRV_PCM_ACCESS_MMAP_COMPLEX) |
1948d5ac70f0Sopenharmony_ci			PCM_BIT(SNDRV_PCM_ACCESS_RW_INTERLEAVED) |
1949d5ac70f0Sopenharmony_ci			PCM_BIT(SNDRV_PCM_ACCESS_RW_NONINTERLEAVED)
1950d5ac70f0Sopenharmony_ci		},
1951d5ac70f0Sopenharmony_ci	},
1952d5ac70f0Sopenharmony_ci	[SND_PCM_HW_PARAM_FORMAT - SND_PCM_HW_PARAM_FIRST_MASK] = {
1953d5ac70f0Sopenharmony_ci		.bits = {
1954d5ac70f0Sopenharmony_ci			/* first 32bits */
1955d5ac70f0Sopenharmony_ci			PCM_BIT(SNDRV_PCM_FORMAT_S8) |
1956d5ac70f0Sopenharmony_ci			PCM_BIT(SNDRV_PCM_FORMAT_U8) |
1957d5ac70f0Sopenharmony_ci			PCM_BIT(SNDRV_PCM_FORMAT_S16_LE) |
1958d5ac70f0Sopenharmony_ci			PCM_BIT(SNDRV_PCM_FORMAT_S16_BE) |
1959d5ac70f0Sopenharmony_ci			PCM_BIT(SNDRV_PCM_FORMAT_U16_LE) |
1960d5ac70f0Sopenharmony_ci			PCM_BIT(SNDRV_PCM_FORMAT_U16_BE) |
1961d5ac70f0Sopenharmony_ci			PCM_BIT(SNDRV_PCM_FORMAT_S24_LE) |
1962d5ac70f0Sopenharmony_ci			PCM_BIT(SNDRV_PCM_FORMAT_S24_BE) |
1963d5ac70f0Sopenharmony_ci			PCM_BIT(SNDRV_PCM_FORMAT_U24_LE) |
1964d5ac70f0Sopenharmony_ci			PCM_BIT(SNDRV_PCM_FORMAT_U24_BE) |
1965d5ac70f0Sopenharmony_ci			PCM_BIT(SNDRV_PCM_FORMAT_S32_LE) |
1966d5ac70f0Sopenharmony_ci			PCM_BIT(SNDRV_PCM_FORMAT_S32_BE) |
1967d5ac70f0Sopenharmony_ci			PCM_BIT(SNDRV_PCM_FORMAT_U32_LE) |
1968d5ac70f0Sopenharmony_ci			PCM_BIT(SNDRV_PCM_FORMAT_U32_BE) |
1969d5ac70f0Sopenharmony_ci			PCM_BIT(SNDRV_PCM_FORMAT_FLOAT_LE) |
1970d5ac70f0Sopenharmony_ci			PCM_BIT(SNDRV_PCM_FORMAT_FLOAT_BE) |
1971d5ac70f0Sopenharmony_ci			PCM_BIT(SNDRV_PCM_FORMAT_FLOAT64_LE) |
1972d5ac70f0Sopenharmony_ci			PCM_BIT(SNDRV_PCM_FORMAT_FLOAT64_BE) |
1973d5ac70f0Sopenharmony_ci			PCM_BIT(SNDRV_PCM_FORMAT_IEC958_SUBFRAME) |
1974d5ac70f0Sopenharmony_ci			PCM_BIT(SNDRV_PCM_FORMAT_IEC958_SUBFRAME) |
1975d5ac70f0Sopenharmony_ci			PCM_BIT(SNDRV_PCM_FORMAT_MU_LAW) |
1976d5ac70f0Sopenharmony_ci			PCM_BIT(SNDRV_PCM_FORMAT_A_LAW) |
1977d5ac70f0Sopenharmony_ci			PCM_BIT(SNDRV_PCM_FORMAT_IMA_ADPCM) |
1978d5ac70f0Sopenharmony_ci			PCM_BIT(SNDRV_PCM_FORMAT_MPEG) |
1979d5ac70f0Sopenharmony_ci			PCM_BIT(SNDRV_PCM_FORMAT_GSM) |
1980d5ac70f0Sopenharmony_ci			PCM_BIT(SNDRV_PCM_FORMAT_S20_LE) |
1981d5ac70f0Sopenharmony_ci			PCM_BIT(SNDRV_PCM_FORMAT_S20_BE) |
1982d5ac70f0Sopenharmony_ci			PCM_BIT(SNDRV_PCM_FORMAT_U20_LE) |
1983d5ac70f0Sopenharmony_ci			PCM_BIT(SNDRV_PCM_FORMAT_U20_BE) |
1984d5ac70f0Sopenharmony_ci			PCM_BIT(SNDRV_PCM_FORMAT_SPECIAL),
1985d5ac70f0Sopenharmony_ci			/* second 32bits */
1986d5ac70f0Sopenharmony_ci			PCM_BIT(SNDRV_PCM_FORMAT_S24_3LE) |
1987d5ac70f0Sopenharmony_ci			PCM_BIT(SNDRV_PCM_FORMAT_S24_3BE) |
1988d5ac70f0Sopenharmony_ci			PCM_BIT(SNDRV_PCM_FORMAT_U24_3LE) |
1989d5ac70f0Sopenharmony_ci			PCM_BIT(SNDRV_PCM_FORMAT_U24_3BE) |
1990d5ac70f0Sopenharmony_ci			PCM_BIT(SNDRV_PCM_FORMAT_S20_3LE) |
1991d5ac70f0Sopenharmony_ci			PCM_BIT(SNDRV_PCM_FORMAT_S20_3BE) |
1992d5ac70f0Sopenharmony_ci			PCM_BIT(SNDRV_PCM_FORMAT_U20_3LE) |
1993d5ac70f0Sopenharmony_ci			PCM_BIT(SNDRV_PCM_FORMAT_U20_3BE) |
1994d5ac70f0Sopenharmony_ci			PCM_BIT(SNDRV_PCM_FORMAT_S18_3LE) |
1995d5ac70f0Sopenharmony_ci			PCM_BIT(SNDRV_PCM_FORMAT_S18_3BE) |
1996d5ac70f0Sopenharmony_ci			PCM_BIT(SNDRV_PCM_FORMAT_U18_3LE) |
1997d5ac70f0Sopenharmony_ci			PCM_BIT(SNDRV_PCM_FORMAT_U18_3BE) |
1998d5ac70f0Sopenharmony_ci			PCM_BIT(SNDRV_PCM_FORMAT_G723_24) |
1999d5ac70f0Sopenharmony_ci			PCM_BIT(SNDRV_PCM_FORMAT_G723_24) |
2000d5ac70f0Sopenharmony_ci			PCM_BIT(SNDRV_PCM_FORMAT_G723_40) |
2001d5ac70f0Sopenharmony_ci			PCM_BIT(SNDRV_PCM_FORMAT_G723_40) |
2002d5ac70f0Sopenharmony_ci			PCM_BIT(SNDRV_PCM_FORMAT_DSD_U8) |
2003d5ac70f0Sopenharmony_ci			PCM_BIT(SNDRV_PCM_FORMAT_DSD_U16_LE) |
2004d5ac70f0Sopenharmony_ci			PCM_BIT(SNDRV_PCM_FORMAT_DSD_U32_LE) |
2005d5ac70f0Sopenharmony_ci			PCM_BIT(SNDRV_PCM_FORMAT_DSD_U16_BE) |
2006d5ac70f0Sopenharmony_ci			PCM_BIT(SNDRV_PCM_FORMAT_DSD_U32_BE)
2007d5ac70f0Sopenharmony_ci		},
2008d5ac70f0Sopenharmony_ci	},
2009d5ac70f0Sopenharmony_ci	[SND_PCM_HW_PARAM_SUBFORMAT - SND_PCM_HW_PARAM_FIRST_MASK] = {
2010d5ac70f0Sopenharmony_ci		.bits = {
2011d5ac70f0Sopenharmony_ci			PCM_BIT(SNDRV_PCM_SUBFORMAT_STD) |
2012d5ac70f0Sopenharmony_ci			PCM_BIT(SNDRV_PCM_SUBFORMAT_MSBITS_MAX) |
2013d5ac70f0Sopenharmony_ci			PCM_BIT(SNDRV_PCM_SUBFORMAT_MSBITS_20) |
2014d5ac70f0Sopenharmony_ci			PCM_BIT(SNDRV_PCM_SUBFORMAT_MSBITS_24),
2015d5ac70f0Sopenharmony_ci		},
2016d5ac70f0Sopenharmony_ci	},
2017d5ac70f0Sopenharmony_ci};
2018d5ac70f0Sopenharmony_ci
2019d5ac70f0Sopenharmony_cistatic const snd_interval_t refine_intervals[SND_PCM_HW_PARAM_LAST_INTERVAL - SND_PCM_HW_PARAM_FIRST_INTERVAL + 1] = {
2020d5ac70f0Sopenharmony_ci	[SND_PCM_HW_PARAM_SAMPLE_BITS - SND_PCM_HW_PARAM_FIRST_INTERVAL] = {
2021d5ac70f0Sopenharmony_ci		.min = 1, .max = UINT_MAX,
2022d5ac70f0Sopenharmony_ci		.openmin = 0, .openmax = 0, .integer = 1, .empty = 0,
2023d5ac70f0Sopenharmony_ci	},
2024d5ac70f0Sopenharmony_ci	[SND_PCM_HW_PARAM_FRAME_BITS - SND_PCM_HW_PARAM_FIRST_INTERVAL] = {
2025d5ac70f0Sopenharmony_ci		.min = 1, .max = UINT_MAX,
2026d5ac70f0Sopenharmony_ci		.openmin = 0, .openmax = 0, .integer = 1, .empty = 0,
2027d5ac70f0Sopenharmony_ci	},
2028d5ac70f0Sopenharmony_ci	[SND_PCM_HW_PARAM_CHANNELS - SND_PCM_HW_PARAM_FIRST_INTERVAL] = {
2029d5ac70f0Sopenharmony_ci		.min = 1, .max = UINT_MAX,
2030d5ac70f0Sopenharmony_ci		.openmin = 0, .openmax = 0, .integer = 1, .empty = 0,
2031d5ac70f0Sopenharmony_ci	},
2032d5ac70f0Sopenharmony_ci	[SND_PCM_HW_PARAM_RATE - SND_PCM_HW_PARAM_FIRST_INTERVAL] = {
2033d5ac70f0Sopenharmony_ci		.min = 1, .max = UINT_MAX,
2034d5ac70f0Sopenharmony_ci		.openmin = 0, .openmax = 0, .integer = 0, .empty = 0,
2035d5ac70f0Sopenharmony_ci	},
2036d5ac70f0Sopenharmony_ci	[SND_PCM_HW_PARAM_PERIOD_TIME - SND_PCM_HW_PARAM_FIRST_INTERVAL] = {
2037d5ac70f0Sopenharmony_ci		.min = 0, .max = UINT_MAX,
2038d5ac70f0Sopenharmony_ci		.openmin = 0, .openmax = 0, .integer = 0, .empty = 0,
2039d5ac70f0Sopenharmony_ci	},
2040d5ac70f0Sopenharmony_ci	[SND_PCM_HW_PARAM_PERIOD_SIZE - SND_PCM_HW_PARAM_FIRST_INTERVAL] = {
2041d5ac70f0Sopenharmony_ci		.min = 0, .max = UINT_MAX,
2042d5ac70f0Sopenharmony_ci		.openmin = 0, .openmax = 0, .integer = 0, .empty = 0,
2043d5ac70f0Sopenharmony_ci	},
2044d5ac70f0Sopenharmony_ci	[SND_PCM_HW_PARAM_PERIOD_BYTES - SND_PCM_HW_PARAM_FIRST_INTERVAL] = {
2045d5ac70f0Sopenharmony_ci		.min = 0, .max = UINT_MAX,
2046d5ac70f0Sopenharmony_ci		.openmin = 0, .openmax = 0, .integer = 0, .empty = 0,
2047d5ac70f0Sopenharmony_ci	},
2048d5ac70f0Sopenharmony_ci	[SND_PCM_HW_PARAM_PERIODS - SND_PCM_HW_PARAM_FIRST_INTERVAL] = {
2049d5ac70f0Sopenharmony_ci		.min = 0, .max = UINT_MAX,
2050d5ac70f0Sopenharmony_ci		.openmin = 0, .openmax = 0, .integer = 0, .empty = 0,
2051d5ac70f0Sopenharmony_ci	},
2052d5ac70f0Sopenharmony_ci	[SND_PCM_HW_PARAM_BUFFER_TIME - SND_PCM_HW_PARAM_FIRST_INTERVAL] = {
2053d5ac70f0Sopenharmony_ci		.min = 1, .max = UINT_MAX,
2054d5ac70f0Sopenharmony_ci		.openmin = 0, .openmax = 0, .integer = 0, .empty = 0,
2055d5ac70f0Sopenharmony_ci	},
2056d5ac70f0Sopenharmony_ci	[SND_PCM_HW_PARAM_BUFFER_SIZE - SND_PCM_HW_PARAM_FIRST_INTERVAL] = {
2057d5ac70f0Sopenharmony_ci		.min = 1, .max = UINT_MAX,
2058d5ac70f0Sopenharmony_ci		.openmin = 0, .openmax = 0, .integer = 1, .empty = 0,
2059d5ac70f0Sopenharmony_ci	},
2060d5ac70f0Sopenharmony_ci	[SND_PCM_HW_PARAM_BUFFER_BYTES - SND_PCM_HW_PARAM_FIRST_INTERVAL] = {
2061d5ac70f0Sopenharmony_ci		.min = 1, .max = UINT_MAX,
2062d5ac70f0Sopenharmony_ci		.openmin = 0, .openmax = 0, .integer = 1, .empty = 0,
2063d5ac70f0Sopenharmony_ci	},
2064d5ac70f0Sopenharmony_ci	[SND_PCM_HW_PARAM_TICK_TIME - SND_PCM_HW_PARAM_FIRST_INTERVAL] = {
2065d5ac70f0Sopenharmony_ci		.min = 0, .max = UINT_MAX,
2066d5ac70f0Sopenharmony_ci		.openmin = 0, .openmax = 0, .integer = 0, .empty = 0,
2067d5ac70f0Sopenharmony_ci	},
2068d5ac70f0Sopenharmony_ci};
2069d5ac70f0Sopenharmony_ci
2070d5ac70f0Sopenharmony_ci#if 0
2071d5ac70f0Sopenharmony_ci#define RULES_DEBUG
2072d5ac70f0Sopenharmony_ci#endif
2073d5ac70f0Sopenharmony_ci
2074d5ac70f0Sopenharmony_ciint snd_pcm_hw_refine_soft(snd_pcm_t *pcm ATTRIBUTE_UNUSED, snd_pcm_hw_params_t *params)
2075d5ac70f0Sopenharmony_ci{
2076d5ac70f0Sopenharmony_ci	unsigned int k;
2077d5ac70f0Sopenharmony_ci	snd_interval_t *i;
2078d5ac70f0Sopenharmony_ci	snd_mask_t *m;
2079d5ac70f0Sopenharmony_ci	unsigned int rstamps[RULES];
2080d5ac70f0Sopenharmony_ci	unsigned int vstamps[SND_PCM_HW_PARAM_LAST_INTERVAL + 1];
2081d5ac70f0Sopenharmony_ci	unsigned int stamp = 2;
2082d5ac70f0Sopenharmony_ci	int changed, again;
2083d5ac70f0Sopenharmony_ci#ifdef RULES_DEBUG
2084d5ac70f0Sopenharmony_ci	snd_output_t *log;
2085d5ac70f0Sopenharmony_ci	snd_output_stdio_attach(&log, stderr, 0);
2086d5ac70f0Sopenharmony_ci	snd_output_printf(log, "refine_soft '%s' (begin)\n", pcm->name);
2087d5ac70f0Sopenharmony_ci	snd_pcm_hw_params_dump(params, log);
2088d5ac70f0Sopenharmony_ci#endif
2089d5ac70f0Sopenharmony_ci
2090d5ac70f0Sopenharmony_ci	for (k = SND_PCM_HW_PARAM_FIRST_MASK; k <= SND_PCM_HW_PARAM_LAST_MASK; k++) {
2091d5ac70f0Sopenharmony_ci		if (!(params->rmask & (1 << k)))
2092d5ac70f0Sopenharmony_ci			continue;
2093d5ac70f0Sopenharmony_ci		changed = snd_mask_refine(hw_param_mask(params, k),
2094d5ac70f0Sopenharmony_ci					  &refine_masks[k - SND_PCM_HW_PARAM_FIRST_MASK]);
2095d5ac70f0Sopenharmony_ci		if (changed)
2096d5ac70f0Sopenharmony_ci			params->cmask |= 1 << k;
2097d5ac70f0Sopenharmony_ci		if (changed < 0)
2098d5ac70f0Sopenharmony_ci			goto _err;
2099d5ac70f0Sopenharmony_ci	}
2100d5ac70f0Sopenharmony_ci
2101d5ac70f0Sopenharmony_ci	for (k = SND_PCM_HW_PARAM_FIRST_INTERVAL; k <= SND_PCM_HW_PARAM_LAST_INTERVAL; k++) {
2102d5ac70f0Sopenharmony_ci		if (!(params->rmask & (1 << k)))
2103d5ac70f0Sopenharmony_ci			continue;
2104d5ac70f0Sopenharmony_ci		changed = snd_interval_refine(hw_param_interval(params, k),
2105d5ac70f0Sopenharmony_ci				      &refine_intervals[k - SND_PCM_HW_PARAM_FIRST_INTERVAL]);
2106d5ac70f0Sopenharmony_ci		if (changed)
2107d5ac70f0Sopenharmony_ci			params->cmask |= 1 << k;
2108d5ac70f0Sopenharmony_ci		if (changed < 0)
2109d5ac70f0Sopenharmony_ci			goto _err;
2110d5ac70f0Sopenharmony_ci	}
2111d5ac70f0Sopenharmony_ci
2112d5ac70f0Sopenharmony_ci	for (k = 0; k < RULES; k++)
2113d5ac70f0Sopenharmony_ci		rstamps[k] = 0;
2114d5ac70f0Sopenharmony_ci	for (k = 0; k <= SND_PCM_HW_PARAM_LAST_INTERVAL; k++)
2115d5ac70f0Sopenharmony_ci		vstamps[k] = (params->rmask & (1 << k)) ? 1 : 0;
2116d5ac70f0Sopenharmony_ci	do {
2117d5ac70f0Sopenharmony_ci		again = 0;
2118d5ac70f0Sopenharmony_ci		for (k = 0; k < RULES; k++) {
2119d5ac70f0Sopenharmony_ci			const snd_pcm_hw_rule_t *r = &refine_rules[k];
2120d5ac70f0Sopenharmony_ci			unsigned int d;
2121d5ac70f0Sopenharmony_ci			int doit = 0;
2122d5ac70f0Sopenharmony_ci			for (d = 0; r->deps[d] >= 0; d++) {
2123d5ac70f0Sopenharmony_ci				if (vstamps[r->deps[d]] > rstamps[k]) {
2124d5ac70f0Sopenharmony_ci					doit = 1;
2125d5ac70f0Sopenharmony_ci					break;
2126d5ac70f0Sopenharmony_ci				}
2127d5ac70f0Sopenharmony_ci			}
2128d5ac70f0Sopenharmony_ci			if (!doit)
2129d5ac70f0Sopenharmony_ci				continue;
2130d5ac70f0Sopenharmony_ci#ifdef RULES_DEBUG
2131d5ac70f0Sopenharmony_ci			snd_output_printf(log, "Rule %d (%p): ", k, r->func);
2132d5ac70f0Sopenharmony_ci			if (r->var >= 0) {
2133d5ac70f0Sopenharmony_ci				snd_output_printf(log, "%s=", snd_pcm_hw_param_name(r->var));
2134d5ac70f0Sopenharmony_ci				snd_pcm_hw_param_dump(params, r->var, log);
2135d5ac70f0Sopenharmony_ci				snd_output_puts(log, " -> ");
2136d5ac70f0Sopenharmony_ci			}
2137d5ac70f0Sopenharmony_ci#endif
2138d5ac70f0Sopenharmony_ci			changed = r->func(params, r);
2139d5ac70f0Sopenharmony_ci#ifdef RULES_DEBUG
2140d5ac70f0Sopenharmony_ci			if (r->var >= 0)
2141d5ac70f0Sopenharmony_ci				snd_pcm_hw_param_dump(params, r->var, log);
2142d5ac70f0Sopenharmony_ci			for (d = 0; r->deps[d] >= 0; d++) {
2143d5ac70f0Sopenharmony_ci				snd_output_printf(log, " %s=", snd_pcm_hw_param_name(r->deps[d]));
2144d5ac70f0Sopenharmony_ci				snd_pcm_hw_param_dump(params, r->deps[d], log);
2145d5ac70f0Sopenharmony_ci			}
2146d5ac70f0Sopenharmony_ci			snd_output_putc(log, '\n');
2147d5ac70f0Sopenharmony_ci#endif
2148d5ac70f0Sopenharmony_ci			rstamps[k] = stamp;
2149d5ac70f0Sopenharmony_ci			if (changed && r->var >= 0) {
2150d5ac70f0Sopenharmony_ci				params->cmask |= 1 << r->var;
2151d5ac70f0Sopenharmony_ci				vstamps[r->var] = stamp;
2152d5ac70f0Sopenharmony_ci				again = 1;
2153d5ac70f0Sopenharmony_ci			}
2154d5ac70f0Sopenharmony_ci			if (changed < 0)
2155d5ac70f0Sopenharmony_ci				goto _err;
2156d5ac70f0Sopenharmony_ci			stamp++;
2157d5ac70f0Sopenharmony_ci		}
2158d5ac70f0Sopenharmony_ci	} while (again);
2159d5ac70f0Sopenharmony_ci	if (!params->msbits) {
2160d5ac70f0Sopenharmony_ci		i = hw_param_interval(params, SND_PCM_HW_PARAM_SAMPLE_BITS);
2161d5ac70f0Sopenharmony_ci		if (snd_interval_single(i))
2162d5ac70f0Sopenharmony_ci			params->msbits = snd_interval_value(i);
2163d5ac70f0Sopenharmony_ci		m = hw_param_mask_c(params, SNDRV_PCM_HW_PARAM_FORMAT);
2164d5ac70f0Sopenharmony_ci		if (snd_mask_single(m)) {
2165d5ac70f0Sopenharmony_ci			snd_pcm_format_t format = snd_mask_min(m);
2166d5ac70f0Sopenharmony_ci			params->msbits = snd_pcm_format_width(format);
2167d5ac70f0Sopenharmony_ci		}
2168d5ac70f0Sopenharmony_ci	}
2169d5ac70f0Sopenharmony_ci
2170d5ac70f0Sopenharmony_ci	if (!params->rate_den) {
2171d5ac70f0Sopenharmony_ci		i = hw_param_interval(params, SND_PCM_HW_PARAM_RATE);
2172d5ac70f0Sopenharmony_ci		if (snd_interval_single(i)) {
2173d5ac70f0Sopenharmony_ci			params->rate_num = snd_interval_value(i);
2174d5ac70f0Sopenharmony_ci			params->rate_den = 1;
2175d5ac70f0Sopenharmony_ci		}
2176d5ac70f0Sopenharmony_ci	}
2177d5ac70f0Sopenharmony_ci	params->rmask = 0;
2178d5ac70f0Sopenharmony_ci	return 0;
2179d5ac70f0Sopenharmony_ci _err:
2180d5ac70f0Sopenharmony_ci#ifdef RULES_DEBUG
2181d5ac70f0Sopenharmony_ci	snd_output_printf(log, "refine_soft '%s' (end-%i)\n", pcm->name, changed);
2182d5ac70f0Sopenharmony_ci	snd_pcm_hw_params_dump(params, log);
2183d5ac70f0Sopenharmony_ci	snd_output_close(log);
2184d5ac70f0Sopenharmony_ci#endif
2185d5ac70f0Sopenharmony_ci	return changed;
2186d5ac70f0Sopenharmony_ci}
2187d5ac70f0Sopenharmony_ci
2188d5ac70f0Sopenharmony_ciint _snd_pcm_hw_params_refine(snd_pcm_hw_params_t *params,
2189d5ac70f0Sopenharmony_ci			      unsigned int vars,
2190d5ac70f0Sopenharmony_ci			      const snd_pcm_hw_params_t *src)
2191d5ac70f0Sopenharmony_ci{
2192d5ac70f0Sopenharmony_ci	int changed, err = 0;
2193d5ac70f0Sopenharmony_ci	unsigned int k;
2194d5ac70f0Sopenharmony_ci	for (k = 0; k <= SND_PCM_HW_PARAM_LAST_INTERVAL; ++k) {
2195d5ac70f0Sopenharmony_ci		if (!(vars & (1 << k)))
2196d5ac70f0Sopenharmony_ci			continue;
2197d5ac70f0Sopenharmony_ci		changed = _snd_pcm_hw_param_refine(params, k, src);
2198d5ac70f0Sopenharmony_ci		if (changed < 0)
2199d5ac70f0Sopenharmony_ci			err = changed;
2200d5ac70f0Sopenharmony_ci	}
2201d5ac70f0Sopenharmony_ci	params->info &= src->info;
2202d5ac70f0Sopenharmony_ci	params->flags = src->flags; /* propagate all flags to slave */
2203d5ac70f0Sopenharmony_ci	return err;
2204d5ac70f0Sopenharmony_ci}
2205d5ac70f0Sopenharmony_ci
2206d5ac70f0Sopenharmony_ciint snd_pcm_hw_refine_slave(snd_pcm_t *pcm, snd_pcm_hw_params_t *params,
2207d5ac70f0Sopenharmony_ci			    int (*cprepare)(snd_pcm_t *pcm,
2208d5ac70f0Sopenharmony_ci					    snd_pcm_hw_params_t *params),
2209d5ac70f0Sopenharmony_ci			    int (*cchange)(snd_pcm_t *pcm,
2210d5ac70f0Sopenharmony_ci					   snd_pcm_hw_params_t *params,
2211d5ac70f0Sopenharmony_ci					   snd_pcm_hw_params_t *sparams),
2212d5ac70f0Sopenharmony_ci			    int (*sprepare)(snd_pcm_t *pcm,
2213d5ac70f0Sopenharmony_ci					    snd_pcm_hw_params_t *params),
2214d5ac70f0Sopenharmony_ci			    int (*schange)(snd_pcm_t *pcm,
2215d5ac70f0Sopenharmony_ci					   snd_pcm_hw_params_t *params,
2216d5ac70f0Sopenharmony_ci					   snd_pcm_hw_params_t *sparams),
2217d5ac70f0Sopenharmony_ci			    int (*srefine)(snd_pcm_t *pcm,
2218d5ac70f0Sopenharmony_ci					   snd_pcm_hw_params_t *sparams))
2219d5ac70f0Sopenharmony_ci
2220d5ac70f0Sopenharmony_ci{
2221d5ac70f0Sopenharmony_ci#ifdef RULES_DEBUG
2222d5ac70f0Sopenharmony_ci	snd_output_t *log;
2223d5ac70f0Sopenharmony_ci#endif
2224d5ac70f0Sopenharmony_ci	snd_pcm_hw_params_t sparams;
2225d5ac70f0Sopenharmony_ci	int err;
2226d5ac70f0Sopenharmony_ci	unsigned int cmask, changed;
2227d5ac70f0Sopenharmony_ci#ifdef RULES_DEBUG
2228d5ac70f0Sopenharmony_ci	snd_output_stdio_attach(&log, stderr, 0);
2229d5ac70f0Sopenharmony_ci#endif
2230d5ac70f0Sopenharmony_ci	err = cprepare(pcm, params);
2231d5ac70f0Sopenharmony_ci	if (err < 0)
2232d5ac70f0Sopenharmony_ci		return err;
2233d5ac70f0Sopenharmony_ci	err = sprepare(pcm, &sparams);
2234d5ac70f0Sopenharmony_ci	if (err < 0) {
2235d5ac70f0Sopenharmony_ci		SNDERR("Slave PCM not usable");
2236d5ac70f0Sopenharmony_ci		return err;
2237d5ac70f0Sopenharmony_ci	}
2238d5ac70f0Sopenharmony_ci#ifdef RULES_DEBUG
2239d5ac70f0Sopenharmony_ci	snd_output_printf(log, "hw_refine_slave - enter '%s'\n", pcm->name);
2240d5ac70f0Sopenharmony_ci#endif
2241d5ac70f0Sopenharmony_ci	do {
2242d5ac70f0Sopenharmony_ci		cmask = params->cmask;
2243d5ac70f0Sopenharmony_ci		params->cmask = 0;
2244d5ac70f0Sopenharmony_ci#ifdef RULES_DEBUG
2245d5ac70f0Sopenharmony_ci		snd_output_printf(log, "schange '%s' (client)\n", pcm->name);
2246d5ac70f0Sopenharmony_ci		snd_pcm_hw_params_dump(params, log);
2247d5ac70f0Sopenharmony_ci		snd_output_printf(log, "schange '%s' (slave)\n", pcm->name);
2248d5ac70f0Sopenharmony_ci		snd_pcm_hw_params_dump(&sparams, log);
2249d5ac70f0Sopenharmony_ci#endif
2250d5ac70f0Sopenharmony_ci		err = schange(pcm, params, &sparams);
2251d5ac70f0Sopenharmony_ci		if (err >= 0) {
2252d5ac70f0Sopenharmony_ci#ifdef RULES_DEBUG
2253d5ac70f0Sopenharmony_ci			snd_output_printf(log, "srefine '%s' (client)\n", pcm->name);
2254d5ac70f0Sopenharmony_ci			snd_pcm_hw_params_dump(params, log);
2255d5ac70f0Sopenharmony_ci			snd_output_printf(log, "srefine '%s' (slave)\n", pcm->name);
2256d5ac70f0Sopenharmony_ci			snd_pcm_hw_params_dump(&sparams, log);
2257d5ac70f0Sopenharmony_ci#endif
2258d5ac70f0Sopenharmony_ci			err = srefine(pcm, &sparams);
2259d5ac70f0Sopenharmony_ci			if (err < 0) {
2260d5ac70f0Sopenharmony_ci#ifdef RULES_DEBUG
2261d5ac70f0Sopenharmony_ci				snd_output_printf(log, "srefine '%s', err < 0 (%i) (client)\n", pcm->name, err);
2262d5ac70f0Sopenharmony_ci				snd_pcm_hw_params_dump(params, log);
2263d5ac70f0Sopenharmony_ci				snd_output_printf(log, "srefine '%s', err < 0 (%i) (slave)\n", pcm->name, err);
2264d5ac70f0Sopenharmony_ci				snd_pcm_hw_params_dump(&sparams, log);
2265d5ac70f0Sopenharmony_ci#endif
2266d5ac70f0Sopenharmony_ci				cchange(pcm, params, &sparams);
2267d5ac70f0Sopenharmony_ci				return err;
2268d5ac70f0Sopenharmony_ci			}
2269d5ac70f0Sopenharmony_ci		} else {
2270d5ac70f0Sopenharmony_ci#ifdef RULES_DEBUG
2271d5ac70f0Sopenharmony_ci			snd_output_printf(log, "schange '%s', err < 0 (%i) (client)\n", pcm->name, err);
2272d5ac70f0Sopenharmony_ci			snd_pcm_hw_params_dump(params, log);
2273d5ac70f0Sopenharmony_ci			snd_output_printf(log, "schange '%s', err < 0 (%i) (slave)\n", pcm->name, err);
2274d5ac70f0Sopenharmony_ci			snd_pcm_hw_params_dump(&sparams, log);
2275d5ac70f0Sopenharmony_ci#endif
2276d5ac70f0Sopenharmony_ci			cchange(pcm, params, &sparams);
2277d5ac70f0Sopenharmony_ci			return err;
2278d5ac70f0Sopenharmony_ci		}
2279d5ac70f0Sopenharmony_ci#ifdef RULES_DEBUG
2280d5ac70f0Sopenharmony_ci		snd_output_printf(log, "cchange '%s'\n", pcm->name);
2281d5ac70f0Sopenharmony_ci#endif
2282d5ac70f0Sopenharmony_ci		err = cchange(pcm, params, &sparams);
2283d5ac70f0Sopenharmony_ci		if (err < 0)
2284d5ac70f0Sopenharmony_ci			return err;
2285d5ac70f0Sopenharmony_ci#ifdef RULES_DEBUG
2286d5ac70f0Sopenharmony_ci		snd_output_printf(log, "refine_soft '%s'\n", pcm->name);
2287d5ac70f0Sopenharmony_ci#endif
2288d5ac70f0Sopenharmony_ci		err = snd_pcm_hw_refine_soft(pcm, params);
2289d5ac70f0Sopenharmony_ci		changed = params->cmask;
2290d5ac70f0Sopenharmony_ci		params->cmask |= cmask;
2291d5ac70f0Sopenharmony_ci		if (err < 0)
2292d5ac70f0Sopenharmony_ci			return err;
2293d5ac70f0Sopenharmony_ci#ifdef RULES_DEBUG
2294d5ac70f0Sopenharmony_ci		snd_output_printf(log, "refine_soft ok '%s'\n", pcm->name);
2295d5ac70f0Sopenharmony_ci#endif
2296d5ac70f0Sopenharmony_ci	} while (changed);
2297d5ac70f0Sopenharmony_ci#ifdef RULES_DEBUG
2298d5ac70f0Sopenharmony_ci	snd_output_printf(log, "refine_slave - leave '%s'\n", pcm->name);
2299d5ac70f0Sopenharmony_ci	snd_output_close(log);
2300d5ac70f0Sopenharmony_ci#endif
2301d5ac70f0Sopenharmony_ci	return 0;
2302d5ac70f0Sopenharmony_ci}
2303d5ac70f0Sopenharmony_ci
2304d5ac70f0Sopenharmony_ciint snd_pcm_hw_params_slave(snd_pcm_t *pcm, snd_pcm_hw_params_t *params,
2305d5ac70f0Sopenharmony_ci			    int (*cchange)(snd_pcm_t *pcm,
2306d5ac70f0Sopenharmony_ci					   snd_pcm_hw_params_t *params,
2307d5ac70f0Sopenharmony_ci					   snd_pcm_hw_params_t *sparams),
2308d5ac70f0Sopenharmony_ci			    int (*sprepare)(snd_pcm_t *pcm,
2309d5ac70f0Sopenharmony_ci					    snd_pcm_hw_params_t *params),
2310d5ac70f0Sopenharmony_ci			    int (*schange)(snd_pcm_t *pcm,
2311d5ac70f0Sopenharmony_ci					   snd_pcm_hw_params_t *params,
2312d5ac70f0Sopenharmony_ci					   snd_pcm_hw_params_t *sparams),
2313d5ac70f0Sopenharmony_ci			    int (*sparams)(snd_pcm_t *pcm,
2314d5ac70f0Sopenharmony_ci					   snd_pcm_hw_params_t *sparams))
2315d5ac70f0Sopenharmony_ci
2316d5ac70f0Sopenharmony_ci{
2317d5ac70f0Sopenharmony_ci	snd_pcm_hw_params_t slave_params;
2318d5ac70f0Sopenharmony_ci	int err;
2319d5ac70f0Sopenharmony_ci	err = sprepare(pcm, &slave_params);
2320d5ac70f0Sopenharmony_ci	if (err < 0)
2321d5ac70f0Sopenharmony_ci		return err;
2322d5ac70f0Sopenharmony_ci	err = schange(pcm, params, &slave_params);
2323d5ac70f0Sopenharmony_ci	if (err < 0)
2324d5ac70f0Sopenharmony_ci		return err;
2325d5ac70f0Sopenharmony_ci	err = sparams(pcm, &slave_params);
2326d5ac70f0Sopenharmony_ci	if (err < 0)
2327d5ac70f0Sopenharmony_ci		cchange(pcm, params, &slave_params);
2328d5ac70f0Sopenharmony_ci	return err;
2329d5ac70f0Sopenharmony_ci}
2330d5ac70f0Sopenharmony_ci
2331d5ac70f0Sopenharmony_cistatic int snd_pcm_sw_params_default(snd_pcm_t *pcm, snd_pcm_sw_params_t *params)
2332d5ac70f0Sopenharmony_ci{
2333d5ac70f0Sopenharmony_ci	assert(pcm && params);
2334d5ac70f0Sopenharmony_ci	assert(pcm->setup);
2335d5ac70f0Sopenharmony_ci	params->proto = SNDRV_PCM_VERSION;
2336d5ac70f0Sopenharmony_ci	params->tstamp_mode = SND_PCM_TSTAMP_NONE;
2337d5ac70f0Sopenharmony_ci	params->tstamp_type = pcm->tstamp_type;
2338d5ac70f0Sopenharmony_ci	params->period_step = 1;
2339d5ac70f0Sopenharmony_ci	params->sleep_min = 0;
2340d5ac70f0Sopenharmony_ci	params->avail_min = pcm->period_size;
2341d5ac70f0Sopenharmony_ci	params->xfer_align = 1;
2342d5ac70f0Sopenharmony_ci	params->start_threshold = 1;
2343d5ac70f0Sopenharmony_ci	params->stop_threshold = pcm->buffer_size;
2344d5ac70f0Sopenharmony_ci	params->silence_threshold = 0;
2345d5ac70f0Sopenharmony_ci	params->silence_size = 0;
2346d5ac70f0Sopenharmony_ci	params->boundary = pcm->buffer_size;
2347d5ac70f0Sopenharmony_ci	/* this should not happen (bad child?) */
2348d5ac70f0Sopenharmony_ci	if (params->boundary == 0)
2349d5ac70f0Sopenharmony_ci		return -EINVAL;
2350d5ac70f0Sopenharmony_ci	while (params->boundary * 2 <= LONG_MAX - pcm->buffer_size)
2351d5ac70f0Sopenharmony_ci		params->boundary *= 2;
2352d5ac70f0Sopenharmony_ci	return 0;
2353d5ac70f0Sopenharmony_ci}
2354d5ac70f0Sopenharmony_ci
2355d5ac70f0Sopenharmony_ci#if 0
2356d5ac70f0Sopenharmony_ci#define REFINE_DEBUG
2357d5ac70f0Sopenharmony_ci#endif
2358d5ac70f0Sopenharmony_ci
2359d5ac70f0Sopenharmony_ciint snd_pcm_hw_refine(snd_pcm_t *pcm, snd_pcm_hw_params_t *params)
2360d5ac70f0Sopenharmony_ci{
2361d5ac70f0Sopenharmony_ci	int res;
2362d5ac70f0Sopenharmony_ci#ifdef REFINE_DEBUG
2363d5ac70f0Sopenharmony_ci	snd_output_t *log;
2364d5ac70f0Sopenharmony_ci	snd_output_stdio_attach(&log, stderr, 0);
2365d5ac70f0Sopenharmony_ci#endif
2366d5ac70f0Sopenharmony_ci	assert(pcm && params);
2367d5ac70f0Sopenharmony_ci#ifdef REFINE_DEBUG
2368d5ac70f0Sopenharmony_ci	snd_output_printf(log, "REFINE called:\n");
2369d5ac70f0Sopenharmony_ci	snd_pcm_hw_params_dump(params, log);
2370d5ac70f0Sopenharmony_ci#endif
2371d5ac70f0Sopenharmony_ci	if (pcm->ops->hw_refine)
2372d5ac70f0Sopenharmony_ci		res = pcm->ops->hw_refine(pcm->op_arg, params);
2373d5ac70f0Sopenharmony_ci	else
2374d5ac70f0Sopenharmony_ci		res = -ENOSYS;
2375d5ac70f0Sopenharmony_ci#ifdef REFINE_DEBUG
2376d5ac70f0Sopenharmony_ci	snd_output_printf(log, "refine done - result = %i\n", res);
2377d5ac70f0Sopenharmony_ci	snd_pcm_hw_params_dump(params, log);
2378d5ac70f0Sopenharmony_ci	snd_output_close(log);
2379d5ac70f0Sopenharmony_ci#endif
2380d5ac70f0Sopenharmony_ci	return res;
2381d5ac70f0Sopenharmony_ci}
2382d5ac70f0Sopenharmony_ci
2383d5ac70f0Sopenharmony_ci/* Install one of the configurations present in configuration
2384d5ac70f0Sopenharmony_ci   space defined by PARAMS.
2385d5ac70f0Sopenharmony_ci   The configuration chosen is that obtained fixing in this order:
2386d5ac70f0Sopenharmony_ci   first access
2387d5ac70f0Sopenharmony_ci   first format
2388d5ac70f0Sopenharmony_ci   first subformat
2389d5ac70f0Sopenharmony_ci   min channels
2390d5ac70f0Sopenharmony_ci   min rate
2391d5ac70f0Sopenharmony_ci   min period_size
2392d5ac70f0Sopenharmony_ci   max periods
2393d5ac70f0Sopenharmony_ci   Return 0 on success otherwise a negative error code
2394d5ac70f0Sopenharmony_ci*/
2395d5ac70f0Sopenharmony_ciint _snd_pcm_hw_params_internal(snd_pcm_t *pcm, snd_pcm_hw_params_t *params)
2396d5ac70f0Sopenharmony_ci{
2397d5ac70f0Sopenharmony_ci	int err;
2398d5ac70f0Sopenharmony_ci	snd_pcm_sw_params_t sw;
2399d5ac70f0Sopenharmony_ci	int fb, min_align;
2400d5ac70f0Sopenharmony_ci	err = snd_pcm_hw_refine(pcm, params);
2401d5ac70f0Sopenharmony_ci	if (err < 0)
2402d5ac70f0Sopenharmony_ci		return err;
2403d5ac70f0Sopenharmony_ci	snd_pcm_hw_params_choose(pcm, params);
2404d5ac70f0Sopenharmony_ci	if (pcm->setup) {
2405d5ac70f0Sopenharmony_ci		err = snd_pcm_hw_free(pcm);
2406d5ac70f0Sopenharmony_ci		if (err < 0)
2407d5ac70f0Sopenharmony_ci			return err;
2408d5ac70f0Sopenharmony_ci	}
2409d5ac70f0Sopenharmony_ci	if (pcm->ops->hw_params)
2410d5ac70f0Sopenharmony_ci		err = pcm->ops->hw_params(pcm->op_arg, params);
2411d5ac70f0Sopenharmony_ci	else
2412d5ac70f0Sopenharmony_ci		err = -ENOSYS;
2413d5ac70f0Sopenharmony_ci	if (err < 0)
2414d5ac70f0Sopenharmony_ci		return err;
2415d5ac70f0Sopenharmony_ci
2416d5ac70f0Sopenharmony_ci	pcm->setup = 1;
2417d5ac70f0Sopenharmony_ci	INTERNAL(snd_pcm_hw_params_get_access)(params, &pcm->access);
2418d5ac70f0Sopenharmony_ci	INTERNAL(snd_pcm_hw_params_get_format)(params, &pcm->format);
2419d5ac70f0Sopenharmony_ci	INTERNAL(snd_pcm_hw_params_get_subformat)(params, &pcm->subformat);
2420d5ac70f0Sopenharmony_ci	INTERNAL(snd_pcm_hw_params_get_channels)(params, &pcm->channels);
2421d5ac70f0Sopenharmony_ci	INTERNAL(snd_pcm_hw_params_get_rate)(params, &pcm->rate, 0);
2422d5ac70f0Sopenharmony_ci	snd_interval_copy(&pcm->periods, &params->intervals[SND_PCM_HW_PARAM_PERIODS - SND_PCM_HW_PARAM_FIRST_INTERVAL]);
2423d5ac70f0Sopenharmony_ci	snd_interval_copy(&pcm->buffer_time, &params->intervals[SND_PCM_HW_PARAM_BUFFER_TIME - SND_PCM_HW_PARAM_FIRST_INTERVAL]);
2424d5ac70f0Sopenharmony_ci	INTERNAL(snd_pcm_hw_params_get_period_time)(params, &pcm->period_time, 0);
2425d5ac70f0Sopenharmony_ci	INTERNAL(snd_pcm_hw_params_get_period_size)(params, &pcm->period_size, 0);
2426d5ac70f0Sopenharmony_ci	INTERNAL(snd_pcm_hw_params_get_buffer_size)(params, &pcm->buffer_size);
2427d5ac70f0Sopenharmony_ci	pcm->sample_bits = snd_pcm_format_physical_width(pcm->format);
2428d5ac70f0Sopenharmony_ci	pcm->frame_bits = pcm->sample_bits * pcm->channels;
2429d5ac70f0Sopenharmony_ci	fb = pcm->frame_bits;
2430d5ac70f0Sopenharmony_ci	min_align = 1;
2431d5ac70f0Sopenharmony_ci	while (fb % 8) {
2432d5ac70f0Sopenharmony_ci		fb *= 2;
2433d5ac70f0Sopenharmony_ci		min_align *= 2;
2434d5ac70f0Sopenharmony_ci	}
2435d5ac70f0Sopenharmony_ci	pcm->min_align = min_align;
2436d5ac70f0Sopenharmony_ci
2437d5ac70f0Sopenharmony_ci	pcm->hw_flags = params->flags;
2438d5ac70f0Sopenharmony_ci	pcm->info = params->info;
2439d5ac70f0Sopenharmony_ci	pcm->msbits = params->msbits;
2440d5ac70f0Sopenharmony_ci	pcm->rate_num = params->rate_num;
2441d5ac70f0Sopenharmony_ci	pcm->rate_den = params->rate_den;
2442d5ac70f0Sopenharmony_ci	pcm->fifo_size = params->fifo_size;
2443d5ac70f0Sopenharmony_ci
2444d5ac70f0Sopenharmony_ci	/* Default sw params */
2445d5ac70f0Sopenharmony_ci	memset(&sw, 0, sizeof(sw));
2446d5ac70f0Sopenharmony_ci	err = snd_pcm_sw_params_default(pcm, &sw);
2447d5ac70f0Sopenharmony_ci	if (err < 0)
2448d5ac70f0Sopenharmony_ci		return err;
2449d5ac70f0Sopenharmony_ci	err = snd_pcm_sw_params(pcm, &sw);
2450d5ac70f0Sopenharmony_ci	if (err < 0)
2451d5ac70f0Sopenharmony_ci		return err;
2452d5ac70f0Sopenharmony_ci
2453d5ac70f0Sopenharmony_ci	if (pcm->mmap_rw ||
2454d5ac70f0Sopenharmony_ci	    pcm->access == SND_PCM_ACCESS_MMAP_INTERLEAVED ||
2455d5ac70f0Sopenharmony_ci	    pcm->access == SND_PCM_ACCESS_MMAP_NONINTERLEAVED ||
2456d5ac70f0Sopenharmony_ci	    pcm->access == SND_PCM_ACCESS_MMAP_COMPLEX) {
2457d5ac70f0Sopenharmony_ci		err = snd_pcm_mmap(pcm);
2458d5ac70f0Sopenharmony_ci	}
2459d5ac70f0Sopenharmony_ci	if (err < 0)
2460d5ac70f0Sopenharmony_ci		return err;
2461d5ac70f0Sopenharmony_ci	return 0;
2462d5ac70f0Sopenharmony_ci}
2463d5ac70f0Sopenharmony_ci
2464