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 #include <stdio.h>
33 #include <stdint.h>
34 #include <string.h>
35 #include <stdarg.h>
36 #include <sound/snd_core.h>
37
ksnd_ctl_num(const char * name)38 int ksnd_ctl_num(const char *name)
39 {
40 struct snd_card *card = NULL;
41 struct snd_kcontrol *k;
42 int num = 0;
43
44 card = snd_card_find_by_name(name);
45 if (!card) {
46 snd_err("no card %s\n", name);
47 return -1;
48 }
49 if (!card->ctl) {
50 snd_err("card %s has no ctl\n", name);
51 return -1;
52 }
53 snd_mutex_lock(card->ctl->ctl_mutex);
54 list_for_each_entry(k, &card->ctl->controls, list) {
55 if (!k->name)
56 break;
57 num++;
58 snd_print("card:%s,kcontrol[%u] \"%s\"\n", name, k->id, k->name);
59 }
60 snd_mutex_unlock(card->ctl->ctl_mutex);
61 return num;
62 }
63
ksnd_ctl_get(const char * name,const char * elem,void * info)64 int ksnd_ctl_get(const char *name, const char *elem, void *info)
65 {
66 struct snd_card *card = NULL;
67 struct snd_kcontrol *k;
68 struct snd_ctl_info *i = info;
69 int ret = -1;
70
71 if (!i)
72 return -1;
73 card = snd_card_find_by_name(name);
74 if (!card) {
75 snd_err("no card %s\n", name);
76 return -1;
77 }
78 if (!card->ctl) {
79 snd_err("card %s has no ctl\n", name);
80 return -1;
81 }
82 snd_mutex_lock(card->ctl->ctl_mutex);
83 list_for_each_entry(k, &card->ctl->controls, list) {
84 if (!strncmp((const char *)k->name, elem, strlen((char *)k->name))) {
85 snd_print("card:%s,kcontrol[%u] \"%s\" found...\n", name, k->id, k->name);
86 ret = k->get(k, i);
87 break;
88 }
89 }
90 snd_mutex_unlock(card->ctl->ctl_mutex);
91 if (ret < 0) {
92 snd_info("card %s ctl doesn't have this elem\n", name);
93 }
94 return ret;
95 }
96
ksnd_ctl_get_bynum(const char * name,const unsigned int elem_num,void * info)97 int ksnd_ctl_get_bynum(const char *name, const unsigned int elem_num, void *info)
98 {
99 struct snd_card *card = NULL;
100 struct snd_kcontrol *k;
101 struct snd_ctl_info *i = info;
102 int ret = -1;
103
104 if (!i)
105 return -1;
106 card = snd_card_find_by_name(name);
107 if (!card) {
108 snd_err("no card %s\n", name);
109 return -1;
110 }
111 if (!card->ctl) {
112 snd_err("card %s has no ctl\n", name);
113 return -1;
114 }
115
116 snd_mutex_lock(card->ctl->ctl_mutex);
117 list_for_each_entry(k, &card->ctl->controls, list) {
118 if (k->id == elem_num) {
119 snd_print("card:%s,kcontrol[%u] \"%s\" found...\n", name, k->id, k->name);
120 ret = k->get(k, i);
121 break;
122 }
123 }
124 snd_mutex_unlock(card->ctl->ctl_mutex);
125 if (ret < 0) {
126 snd_info("card %s ctl doesn't have this elem\n", name);
127 }
128 return ret;
129 }
130
ksnd_ctl_set(const char * name,const char * elem,unsigned int val)131 int ksnd_ctl_set(const char *name, const char *elem, unsigned int val)
132 {
133 struct snd_card *card = NULL;
134 struct snd_kcontrol *k;
135 int ret = -1;
136
137 card = snd_card_find_by_name(name);
138 if (!card) {
139 snd_err("no card %s\n", name);
140 return -1;
141 }
142 if (!card->ctl) {
143 snd_err("card %s has no ctl\n", name);
144 return -1;
145 }
146
147 snd_mutex_lock(card->ctl->ctl_mutex);
148 list_for_each_entry(k, &card->ctl->controls, list) {
149 if (!strncmp((const char *)k->name, elem, strlen((char *)k->name))) {
150 snd_print("card:%s,kcontrol[%u] \"%s\" found...\n", name, k->id, k->name);
151 ret = k->set(k, val);
152 break;
153 }
154 }
155 snd_mutex_unlock(card->ctl->ctl_mutex);
156 if (ret < 0)
157 snd_err("card %s ctl doesn't have this elem\n", name);
158 return ret;
159 }
160
ksnd_ctl_set_bynum(const char * name,const unsigned int elem_num,unsigned int val)161 int ksnd_ctl_set_bynum(const char *name, const unsigned int elem_num, unsigned int val)
162 {
163 struct snd_card *card = NULL;
164 struct snd_kcontrol *k;
165 int ret = -1;
166
167 card = snd_card_find_by_name(name);
168 if (!card) {
169 snd_err("no card %s\n", name);
170 return -1;
171 }
172 if (!card->ctl) {
173 snd_err("card %s has no ctl\n", name);
174 return -1;
175 }
176 snd_mutex_lock(card->ctl->ctl_mutex);
177 list_for_each_entry(k, &card->ctl->controls, list) {
178 if (k->id == elem_num) {
179 snd_print("card:%s,kcontrol[%u] \"%s\" found...\n", name, k->id, k->name);
180 ret = k->set(k, val);
181 break;
182 }
183 }
184 snd_mutex_unlock(card->ctl->ctl_mutex);
185 if (ret < 0)
186 snd_err("card %s ctl doesn't have this elem\n", name);
187 return ret;
188 }
189
ksnd_ctl_set_multi_args(const char * name,const char * elem,int num,...)190 int ksnd_ctl_set_multi_args(const char *name, const char *elem, int num, ...)
191 {
192 struct snd_card *card = NULL;
193 struct snd_kcontrol *k, *kcontrol = NULL;
194 int j, ret = -1;
195 va_list ap;
196 unsigned long *value;
197
198 card = snd_card_find_by_name(name);
199 if (!card) {
200 snd_err("no card %s\n", name);
201 return -1;
202 }
203 if (!card->ctl) {
204 snd_err("card %s has no ctl\n", name);
205 return -1;
206 }
207
208 snd_mutex_lock(card->ctl->ctl_mutex);
209 list_for_each_entry(k, &card->ctl->controls, list) {
210 if (!strncmp((const char *)k->name, elem, strlen((char *)k->name))) {
211 kcontrol = k;
212 break;
213 }
214 }
215 if (!kcontrol) {
216 snd_err("card %s ctl doesn't have this elem\n", name);
217 goto err;
218 }
219 if (kcontrol->count != num) {
220 snd_err("actual kcontrol count=%d, but arg num is %d\n",
221 kcontrol->count, num);
222 goto err;
223 }
224 value = snd_malloc(sizeof(unsigned long) * kcontrol->count);
225
226 va_start(ap, num);
227 for (j = 0; j < num; j++) {
228 value[j] = va_arg(ap, unsigned long);
229 snd_print("arg%d is :%d\n", j, value[j]);
230 }
231 va_end(ap);
232
233 ret = kcontrol->set(kcontrol, (unsigned long)value);
234 err:
235 snd_mutex_unlock(card->ctl->ctl_mutex);
236 return ret;
237 }
238
ksnd_ctl_add_elem(const char * name,void * info)239 int ksnd_ctl_add_elem(const char *name, void *info)
240 {
241 struct snd_card *card = NULL;
242 struct snd_ctl_info *i = info;
243 int ret;
244
245 if (!i)
246 return -1;
247 card = snd_card_find_by_name(name);
248 if (!card) {
249 snd_err("no card %s\n", name);
250 return -1;
251 }
252 if (!card->ctl) {
253 snd_err("card %s has no ctl\n", name);
254 return -1;
255 }
256
257 snd_mutex_lock(card->ctl->ctl_mutex);
258 ret = snd_ctl_add_elem(card->ctl, i);
259 snd_mutex_unlock(card->ctl->ctl_mutex);
260 return ret;
261 }
262
ksnd_ctl_remove_elem(const char * name,const unsigned int elem_num)263 int ksnd_ctl_remove_elem(const char *name, const unsigned int elem_num)
264 {
265 struct snd_card *card = NULL;
266 struct snd_kcontrol *k = NULL;
267 int ret = -1;
268
269 card = snd_card_find_by_name(name);
270 if (!card) {
271 snd_err("no card %s\n", name);
272 return -1;
273 }
274 if (!card->ctl) {
275 snd_err("card %s has no ctl\n", name);
276 return -1;
277 }
278
279 snd_mutex_lock(card->ctl->ctl_mutex);
280 list_for_each_entry(k, &card->ctl->controls, list) {
281 if (k->id == elem_num) {
282 ret = snd_ctl_remove_elem(card->ctl, k);
283 break;
284 }
285 }
286 snd_mutex_unlock(card->ctl->ctl_mutex);
287 return ret;
288 }
289