1 /*
2 * Copyright (c) 2019-2025 Allwinner Technology Co., Ltd. ALL rights reserved.
3 *
4 * Allwinner is a trademark of Allwinner Technology Co.,Ltd., registered in
5 * the the people's Republic of China and other countries.
6 * All Allwinner Technology Co.,Ltd. trademarks are used with permission.
7 *
8 * DISCLAIMER
9 * THIRD PARTY LICENCES MAY BE REQUIRED TO IMPLEMENT THE SOLUTION/PRODUCT.
10 * IF YOU NEED TO INTEGRATE THIRD PARTY’S TECHNOLOGY (SONY, DTS, DOLBY, AVS OR MPEGLA, ETC.)
11 * IN ALLWINNERS’SDK OR PRODUCTS, YOU SHALL BE SOLELY RESPONSIBLE TO OBTAIN
12 * ALL APPROPRIATELY REQUIRED THIRD PARTY LICENCES.
13 * ALLWINNER SHALL HAVE NO WARRANTY, INDEMNITY OR OTHER OBLIGATIONS WITH RESPECT TO MATTERS
14 * COVERED UNDER ANY REQUIRED THIRD PARTY LICENSE.
15 * YOU ARE SOLELY RESPONSIBLE FOR YOUR USAGE OF THIRD PARTY’S TECHNOLOGY.
16 *
17 *
18 * THIS SOFTWARE IS PROVIDED BY ALLWINNER"AS IS" AND TO THE MAXIMUM EXTENT
19 * PERMITTED BY LAW, ALLWINNER EXPRESSLY DISCLAIMS ALL WARRANTIES OF ANY KIND,
20 * WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING WITHOUT LIMITATION REGARDING
21 * THE TITLE, NON-INFRINGEMENT, ACCURACY, CONDITION, COMPLETENESS, PERFORMANCE
22 * OR MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
23 * IN NO EVENT SHALL ALLWINNER BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
26 * LOSS OF USE, DATA, OR PROFITS, OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
28 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
30 * OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32
33 #include <stdio.h>
34 #include <stdint.h>
35 #include <string.h>
36 #include <sound/snd_core.h>
37 #include <sound/snd_pcm.h>
38 #include <sound/snd_misc.h>
39
40 #define HW_PARAM(v) [SND_PCM_HW_PARAM_##v] = #v
41 static const char * const snd_pcm_hw_param_names[] = {
42 HW_PARAM(ACCESS),
43 HW_PARAM(FORMAT),
44 HW_PARAM(SAMPLE_BITS),
45 HW_PARAM(FRAME_BITS),
46 HW_PARAM(CHANNELS),
47 HW_PARAM(RATE),
48 HW_PARAM(PERIOD_TIME),
49 HW_PARAM(PERIOD_SIZE),
50 HW_PARAM(PERIOD_BYTES),
51 HW_PARAM(PERIODS),
52 HW_PARAM(BUFFER_TIME),
53 HW_PARAM(BUFFER_SIZE),
54 HW_PARAM(BUFFER_BYTES),
55 };
56
snd_pcm_hw_param_name(snd_pcm_hw_param_t param)57 const char *snd_pcm_hw_param_name(snd_pcm_hw_param_t param)
58 {
59 return snd_pcm_hw_param_names[param];
60 }
61
snd_range_refine(snd_interval_t * i,const snd_interval_t * v)62 int snd_range_refine(snd_interval_t *i, const snd_interval_t *v)
63 {
64 int changed = 0;
65 if (snd_range_empty(i))
66 return -EINVAL;
67
68 if (i->range.min < v->range.min) {
69 i->range.min = v->range.min;
70 i->range.openmin = v->range.openmin;
71 changed = 1;
72 } else if (i->range.min == v->range.min && !i->range.openmin && v->range.openmin) {
73 i->range.openmin = 1;
74 changed = 1;
75 }
76
77 if (i->range.max > v->range.max) {
78 i->range.max = v->range.max;
79 i->range.openmax = v->range.openmax;
80 changed = 1;
81 } else if (i->range.max == v->range.max && !i->range.openmax && v->range.openmax) {
82 i->range.openmax = 1;
83 changed = 1;
84 }
85
86 if (!i->range.integer && v->range.integer) {
87 i->range.integer = 1;
88 changed = 1;
89 }
90 if (i->range.integer) {
91 if (i->range.openmin) {
92 i->range.min++;
93 i->range.openmin = 0;
94 }
95 if (i->range.openmax) {
96 i->range.max--;
97 i->range.openmax = 0;
98 }
99 } else if (!i->range.openmin && !i->range.openmax && i->range.min == i->range.max) {
100 i->range.integer = 1;
101 }
102
103 if (snd_range_checkempty(i)) {
104 snd_range_none(i);
105 return -EINVAL;
106 }
107 return changed;
108 }
109
snd_range_refine_first(snd_interval_t * i)110 int snd_range_refine_first(snd_interval_t *i)
111 {
112 if (snd_range_empty(i))
113 return -EINVAL;
114 if (snd_range_single(i))
115 return 0;
116 i->range.max = i->range.min;
117 i->range.openmax = i->range.openmin;
118 if (i->range.openmax)
119 i->range.max++;
120 return 1;
121 }
122
snd_range_refine_last(snd_interval_t * i)123 int snd_range_refine_last(snd_interval_t *i)
124 {
125 if (snd_range_empty(i))
126 return -EINVAL;
127 if (snd_range_single(i))
128 return 0;
129 i->range.min = i->range.max;
130 i->range.openmin = i->range.openmax;
131 if (i->range.openmin)
132 i->range.min--;
133 return 1;
134 }
135
snd_range_refine_min(snd_interval_t * i,unsigned int min,int openmin)136 int snd_range_refine_min(snd_interval_t *i, unsigned int min, int openmin)
137 {
138 int changed = 0;
139 if (snd_range_empty(i))
140 return -ENOENT;
141 if (i->range.min < min) {
142 i->range.min = min;
143 i->range.openmin = openmin;
144 changed = 1;
145 } else if (i->range.min == min && !i->range.openmin && openmin) {
146 i->range.openmin = 1;
147 changed = 1;
148 }
149 if (i->range.integer) {
150 if (i->range.openmin) {
151 i->range.min++;
152 i->range.openmin = 0;
153 }
154 }
155 if (snd_range_checkempty(i)) {
156 snd_range_none(i);
157 return -EINVAL;
158 }
159 return changed;
160 }
161
snd_range_refine_max(snd_interval_t * i,unsigned int max,int openmax)162 int snd_range_refine_max(snd_interval_t *i, unsigned int max, int openmax)
163 {
164 int changed = 0;
165 if (snd_range_empty(i))
166 return -ENOENT;
167 if (i->range.max > max) {
168 i->range.max = max;
169 i->range.openmax = openmax;
170 changed = 1;
171 } else if (i->range.max == max && !i->range.openmax && openmax) {
172 i->range.openmax = 1;
173 changed = 1;
174 }
175 if (i->range.integer) {
176 if (i->range.openmax) {
177 i->range.max--;
178 i->range.openmax = 0;
179 }
180 }
181 if (snd_range_checkempty(i)) {
182 snd_range_none(i);
183 return -EINVAL;
184 }
185 return changed;
186 }
187
snd_range_refine_set(snd_interval_t * i,unsigned int val)188 int snd_range_refine_set(snd_interval_t *i, unsigned int val)
189 {
190 snd_interval_t t;
191 t.range.empty = 0;
192 t.range.min = t.range.max = val;
193 t.range.openmin = t.range.openmax = 0;
194 t.range.integer = 1;
195 return snd_range_refine(i, &t);
196 }
197
snd_range_add(const snd_interval_t * a,const snd_interval_t * b,snd_interval_t * c)198 void snd_range_add(const snd_interval_t *a, const snd_interval_t *b, snd_interval_t *c)
199 {
200 if (a->range.empty || b->range.empty) {
201 snd_range_none(c);
202 return;
203 }
204 c->range.empty = 0;
205 c->range.min = add(a->range.min, b->range.min);
206 c->range.openmin = (a->range.openmin || b->range.openmin);
207 c->range.max = add(a->range.max, b->range.max);
208 c->range.openmax = (a->range.openmax || b->range.openmax);
209 c->range.integer = (a->range.integer && b->range.integer);
210 }
211
snd_interval_sub(const snd_interval_t * a,const snd_interval_t * b,snd_interval_t * c)212 void snd_interval_sub(const snd_interval_t *a, const snd_interval_t *b, snd_interval_t *c)
213 {
214 if (a->range.empty || b->range.empty) {
215 snd_range_none(c);
216 return;
217 }
218 c->range.empty = 0;
219 c->range.min = sub(a->range.min, b->range.max);
220 c->range.openmin = (a->range.openmin || b->range.openmax);
221 c->range.max = add(a->range.max, b->range.min);
222 c->range.openmax = (a->range.openmax || b->range.openmin);
223 c->range.integer = (a->range.integer && b->range.integer);
224 }
225
snd_range_mul(const snd_interval_t * a,const snd_interval_t * b,snd_interval_t * c)226 void snd_range_mul(const snd_interval_t *a, const snd_interval_t *b, snd_interval_t *c)
227 {
228 if (a->range.empty || b->range.empty) {
229 snd_range_none(c);
230 return;
231 }
232 c->range.empty = 0;
233 c->range.min = mul(a->range.min, b->range.min);
234 c->range.openmin = (a->range.openmin || b->range.openmin);
235 c->range.max = mul(a->range.max, b->range.max);
236 c->range.openmax = (a->range.openmax || b->range.openmax);
237 c->range.integer = (a->range.integer && b->range.integer);
238 }
239
240 /**
241 * snd_range_div - refine the range value with division
242 * @a: dividend
243 * @b: divisor
244 * @c: quotient
245 *
246 * c = a / b
247 *
248 * Returns non-zero if the value is changed, zero if not changed.
249 */
snd_range_div(const snd_interval_t * a,const snd_interval_t * b,snd_interval_t * c)250 void snd_range_div(const snd_interval_t *a, const snd_interval_t *b, snd_interval_t *c)
251 {
252 unsigned int r;
253 if (a->range.empty || b->range.empty) {
254 snd_range_none(c);
255 return;
256 }
257 c->range.empty = 0;
258 c->range.min = div32(a->range.min, b->range.max, &r);
259 c->range.openmin = (r || a->range.openmin || b->range.openmax);
260 if (b->range.min > 0) {
261 c->range.max = div32(a->range.max, b->range.min, &r);
262 if (r) {
263 c->range.max++;
264 c->range.openmax = 1;
265 } else {
266 c->range.openmax = (a->range.openmax || b->range.openmin);
267 }
268 } else {
269 c->range.max = UINT_MAX;
270 c->range.openmax = 0;
271 }
272 c->range.integer = 0;
273 }
274
275 /* a * b / c */
snd_range_muldiv(const snd_interval_t * a,const snd_interval_t * b,const snd_interval_t * c,snd_interval_t * d)276 void snd_range_muldiv(const snd_interval_t *a, const snd_interval_t *b,
277 const snd_interval_t *c, snd_interval_t *d)
278 {
279 unsigned int r;
280 if (a->range.empty || b->range.empty || c->range.empty) {
281 snd_range_none(d);
282 return;
283 }
284 d->range.empty = 0;
285 d->range.min = muldiv32(a->range.min, b->range.min, c->range.max, &r);
286 d->range.openmin = (r || a->range.openmin || b->range.openmin || c->range.openmax);
287 d->range.max = muldiv32(a->range.max, b->range.max, c->range.min, &r);
288 if (r) {
289 d->range.max++;
290 d->range.openmax = 1;
291 } else
292 d->range.openmax = (a->range.openmax || b->range.openmax || c->range.openmin);
293 d->range.integer = 0;
294 }
295
296 /**
297 * snd_range_muldivk - refine the range value
298 * @a: dividend 1
299 * @b: dividend 2
300 * @k: divisor (as integer)
301 * @c: result
302 *
303 * c = a * b / k
304 *
305 * Returns non-zero if the value is changed, zero if not changed.
306 */
snd_range_muldivk(const snd_interval_t * a,const snd_interval_t * b,unsigned int k,snd_interval_t * c)307 void snd_range_muldivk(const snd_interval_t *a, const snd_interval_t *b,
308 unsigned int k, snd_interval_t *c)
309 {
310 unsigned int r;
311 if (a->range.empty || b->range.empty) {
312 snd_range_none(c);
313 return;
314 }
315 c->range.empty = 0;
316 c->range.min = muldiv32(a->range.min, b->range.min, k, &r);
317 c->range.openmin = (r || a->range.openmin || b->range.openmin);
318 c->range.max = muldiv32(a->range.max, b->range.max, k, &r);
319 if (r) {
320 c->range.max++;
321 c->range.openmax = 1;
322 } else {
323 c->range.openmax = (a->range.openmax || b->range.openmax);
324 }
325 c->range.integer = 0;
326 }
327
328 /**
329 * snd_range_mulkdiv - refine the range value
330 * @a: dividend 1
331 * @k: dividend 2 (as integer)
332 * @b: divisor
333 * @c: result
334 *
335 * c = a * k / b
336 *
337 * Returns non-zero if the value is changed, zero if not changed.
338 */
snd_range_mulkdiv(const snd_interval_t * a,unsigned int k,const snd_interval_t * b,snd_interval_t * c)339 void snd_range_mulkdiv(const snd_interval_t *a, unsigned int k,
340 const snd_interval_t *b, snd_interval_t *c)
341 {
342 unsigned int r;
343 if (a->range.empty || b->range.empty) {
344 snd_range_none(c);
345 return;
346 }
347 c->range.empty = 0;
348 c->range.min = muldiv32(a->range.min, k, b->range.max, &r);
349 c->range.openmin = (r || a->range.openmin || b->range.openmax);
350 if (b->range.min > 0) {
351 c->range.max = muldiv32(a->range.max, k, b->range.min, &r);
352 if (r) {
353 c->range.max++;
354 c->range.openmax = 1;
355 } else {
356 c->range.openmax = (a->range.openmax || b->range.openmin);
357 }
358 } else {
359 c->range.max = UINT_MAX;
360 c->range.openmax = 0;
361 }
362 c->range.integer = 0;
363 }
364
365 /**
366 * snd_range_list - refine the range value from the list
367 * @i: the interval value to refine
368 * @count: the number of elements in the list
369 * @list: the value list
370 * @mask: the bit-mask to evaluate
371 *
372 * Refines the interval value from the list.
373 * When mask is non-zero, only the elements corresponding to bit 1 are
374 * evaluated.
375 *
376 * Return: Positive if the value is changed, zero if it's not changed, or a
377 * negative error code.
378 */
snd_range_list(snd_interval_t * i,unsigned int count,const unsigned int * list,unsigned int mask)379 int snd_range_list(snd_interval_t *i, unsigned int count,
380 const unsigned int *list, unsigned int mask)
381 {
382 unsigned int k;
383 snd_interval_t list_range;
384
385 if (!count) {
386 i->range.empty = 1;
387 return -EINVAL;
388 }
389 snd_range_any(&list_range);
390 list_range.range.min = UINT_MAX;
391 list_range.range.max = 0;
392 for (k = 0; k < count; k++) {
393 if (mask && !(mask & (1 << k)))
394 continue;
395 if (!snd_range_test(i, list[k]))
396 continue;
397 list_range.range.min = min(list_range.range.min, list[k]);
398 list_range.range.max = max(list_range.range.max, list[k]);
399 }
400 return snd_range_refine(i, &list_range);
401 }
402
snd_pcm_hw_rule_mul(struct snd_pcm_hw_params * params,struct snd_pcm_hw_rule * rule)403 int snd_pcm_hw_rule_mul(struct snd_pcm_hw_params *params, struct snd_pcm_hw_rule *rule)
404 {
405 snd_interval_t t;
406 snd_range_mul(hw_param_interval(params, rule->deps[0]),
407 hw_param_interval(params, rule->deps[1]), &t);
408 return snd_range_refine(hw_param_interval(params, rule->var), &t);
409 }
410
snd_pcm_hw_rule_div(struct snd_pcm_hw_params * params,struct snd_pcm_hw_rule * rule)411 int snd_pcm_hw_rule_div(struct snd_pcm_hw_params *params, struct snd_pcm_hw_rule *rule)
412 {
413 snd_interval_t t;
414 snd_range_div(hw_param_interval(params, rule->deps[0]),
415 hw_param_interval(params, rule->deps[1]), &t);
416 return snd_range_refine(hw_param_interval(params, rule->var), &t);
417 }
418
snd_pcm_hw_rule_muldivk(struct snd_pcm_hw_params * params,struct snd_pcm_hw_rule * rule)419 int snd_pcm_hw_rule_muldivk(struct snd_pcm_hw_params *params, struct snd_pcm_hw_rule *rule)
420 {
421 snd_interval_t t;
422 snd_range_muldivk(hw_param_interval(params, rule->deps[0]),
423 hw_param_interval(params, rule->deps[1]),
424 (unsigned long) rule->private_data, &t);
425 return snd_range_refine(hw_param_interval(params, rule->var), &t);
426 }
427
snd_pcm_hw_rule_mulkdiv(struct snd_pcm_hw_params * params,struct snd_pcm_hw_rule * rule)428 int snd_pcm_hw_rule_mulkdiv(struct snd_pcm_hw_params *params, struct snd_pcm_hw_rule *rule)
429 {
430 snd_interval_t t;
431 snd_range_mulkdiv(hw_param_interval_c(params, rule->deps[0]),
432 (unsigned long) rule->private_data,
433 hw_param_interval_c(params, rule->deps[1]), &t);
434 return snd_range_refine(hw_param_interval(params, rule->var), &t);
435 }
436
snd_pcm_hw_rule_format(struct snd_pcm_hw_params * params,struct snd_pcm_hw_rule * rule)437 int snd_pcm_hw_rule_format(struct snd_pcm_hw_params *params, struct snd_pcm_hw_rule *rule)
438 {
439 unsigned int k;
440 snd_interval_t *dep_i = hw_param_interval(params, rule->deps[0]);
441 snd_interval_t tmp_i;
442 snd_interval_t *interval = hw_param_interval(params, SND_PCM_HW_PARAM_FORMAT);
443 snd_mask_any(&tmp_i);
444 for (k = 0; k <= SND_PCM_FORMAT_LAST; ++k) {
445 int bits;
446 if (! snd_mask_test(interval, k))
447 continue;
448 bits = snd_pcm_format_physical_width(k);
449 if (bits <= 0)
450 continue; /* ignore invalid formats */
451 if ((unsigned)bits < dep_i->range.min || (unsigned)bits > dep_i->range.max)
452 snd_mask_reset(&tmp_i, k);
453 }
454 return snd_mask_refine(interval, &tmp_i);
455 }
456
snd_pcm_hw_rule_sample_bits(struct snd_pcm_hw_params * params,struct snd_pcm_hw_rule * rule)457 int snd_pcm_hw_rule_sample_bits(struct snd_pcm_hw_params *params, struct snd_pcm_hw_rule *rule)
458 {
459 snd_interval_t t;
460 unsigned int k;
461 t.range.min = UINT_MAX;
462 t.range.max = 0;
463 t.range.openmin = 0;
464 t.range.openmax = 0;
465 for (k = 0; k <= SND_PCM_FORMAT_LAST; ++k) {
466 int bits;
467 if (! snd_mask_test(hw_param_interval(params, SND_PCM_HW_PARAM_FORMAT), k))
468 continue;
469 bits = snd_pcm_format_physical_width(k);
470 if (bits <= 0)
471 continue; /* ignore invalid formats */
472 if (t.range.min > (unsigned)bits)
473 t.range.min = bits;
474 if (t.range.max < (unsigned)bits)
475 t.range.max = bits;
476 }
477 t.range.integer = 1;
478 return snd_range_refine(hw_param_interval(params, rule->var), &t);
479 }
480
snd_pcm_hw_rule_rate(struct snd_pcm_hw_params * params,struct snd_pcm_hw_rule * rule)481 int snd_pcm_hw_rule_rate(struct snd_pcm_hw_params *params, struct snd_pcm_hw_rule *rule)
482 {
483 struct snd_pcm_hardware *hw = rule->private_data;
484 return snd_range_list(hw_param_interval(params, rule->var),
485 snd_pcm_known_rates.count,
486 snd_pcm_known_rates.list, hw->rates);
487 }
488
snd_pcm_hw_rule_buffer_bytes_max(struct snd_pcm_hw_params * params,struct snd_pcm_hw_rule * rule)489 int snd_pcm_hw_rule_buffer_bytes_max(struct snd_pcm_hw_params *params,
490 struct snd_pcm_hw_rule *rule)
491 {
492 snd_interval_t t;
493 struct snd_pcm_substream *substream = rule->private_data;
494 t.range.min = 0;
495 t.range.max = substream->runtime->hw.buffer_bytes_max;
496 t.range.openmin = 0;
497 t.range.openmax = 0;
498 t.range.integer = 1;
499 return snd_range_refine(hw_param_interval(params, rule->var), &t);
500 }
501