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