1 /*
2 Copyright(c) 2014-2015 Intel Corporation
3 All rights reserved.
4
5 This library is free software; you can redistribute it and/or modify
6 it under the terms of the GNU Lesser General Public License as
7 published by the Free Software Foundation; either version 2.1 of
8 the License, or (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU Lesser General Public License for more details.
14
15 Authors: Mengdong Lin <mengdong.lin@intel.com>
16 Yao Jin <yao.jin@intel.com>
17 Liam Girdwood <liam.r.girdwood@linux.intel.com>
18 */
19
20 #include "tplg_local.h"
21
22 #ifndef DOC_HIDDEN
23 #define ENUM_VAL_SIZE (SNDRV_CTL_ELEM_ID_NAME_MAXLEN >> 2)
24
25 struct ctl_access_elem {
26 const char *name;
27 unsigned int value;
28 };
29 #endif /* DOC_HIDDEN */
30
31 /* CTL access strings and codes */
32 /* place the multi-bit values on top - like read_write - for save */
33 static const struct ctl_access_elem ctl_access[] = {
34 {"read_write", SNDRV_CTL_ELEM_ACCESS_READWRITE},
35 {"tlv_read_write", SNDRV_CTL_ELEM_ACCESS_TLV_READWRITE},
36 {"read", SNDRV_CTL_ELEM_ACCESS_READ},
37 {"write", SNDRV_CTL_ELEM_ACCESS_WRITE},
38 {"volatile", SNDRV_CTL_ELEM_ACCESS_VOLATILE},
39 {"tlv_read", SNDRV_CTL_ELEM_ACCESS_TLV_READ},
40 {"tlv_write", SNDRV_CTL_ELEM_ACCESS_TLV_WRITE},
41 {"tlv_command", SNDRV_CTL_ELEM_ACCESS_TLV_COMMAND},
42 {"inactive", SNDRV_CTL_ELEM_ACCESS_INACTIVE},
43 {"lock", SNDRV_CTL_ELEM_ACCESS_LOCK},
44 {"owner", SNDRV_CTL_ELEM_ACCESS_OWNER},
45 {"tlv_callback", SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK},
46 };
47
48 /* find CTL access strings and conver to values */
parse_access_values(snd_config_t *cfg, struct snd_soc_tplg_ctl_hdr *hdr)49 static int parse_access_values(snd_config_t *cfg,
50 struct snd_soc_tplg_ctl_hdr *hdr)
51 {
52 snd_config_iterator_t i, next;
53 snd_config_t *n;
54 const char *value = NULL;
55 unsigned int j;
56
57 tplg_dbg(" Access:");
58
59 snd_config_for_each(i, next, cfg) {
60 n = snd_config_iterator_entry(i);
61
62 /* get value */
63 if (snd_config_get_string(n, &value) < 0)
64 continue;
65
66 /* match access value and set flags */
67 for (j = 0; j < ARRAY_SIZE(ctl_access); j++) {
68 if (strcmp(value, ctl_access[j].name) == 0) {
69 hdr->access |= ctl_access[j].value;
70 tplg_dbg("\t%s", value);
71 break;
72 }
73 }
74 }
75
76 return 0;
77 }
78
79 /* Parse Access */
parse_access(snd_config_t *cfg, struct snd_soc_tplg_ctl_hdr *hdr)80 int parse_access(snd_config_t *cfg,
81 struct snd_soc_tplg_ctl_hdr *hdr)
82 {
83 snd_config_iterator_t i, next;
84 snd_config_t *n;
85 const char *id;
86 int err = 0;
87
88 snd_config_for_each(i, next, cfg) {
89
90 n = snd_config_iterator_entry(i);
91 if (snd_config_get_id(n, &id) < 0)
92 continue;
93
94 if (strcmp(id, "access") == 0) {
95 err = parse_access_values(n, hdr);
96 if (err < 0) {
97 SNDERR("failed to parse access");
98 return err;
99 }
100 continue;
101 }
102 }
103
104 return err;
105 }
106
107 /* Save Access */
tplg_save_access(snd_tplg_t *tplg ATTRIBUTE_UNUSED, struct snd_soc_tplg_ctl_hdr *hdr, struct tplg_buf *dst, const char *pfx)108 static int tplg_save_access(snd_tplg_t *tplg ATTRIBUTE_UNUSED,
109 struct snd_soc_tplg_ctl_hdr *hdr,
110 struct tplg_buf *dst, const char *pfx)
111 {
112 const char *last;
113 unsigned int j, count, access, cval;
114 int err;
115
116 if (hdr->access == 0)
117 return 0;
118
119 access = hdr->access;
120 for (j = 0, count = 0, last = NULL; j < ARRAY_SIZE(ctl_access); j++) {
121 cval = ctl_access[j].value;
122 if ((access & cval) == cval) {
123 access &= ~cval;
124 last = ctl_access[j].name;
125 count++;
126 }
127 }
128 if (count == 1)
129 return tplg_save_printf(dst, pfx, "access.0 %s\n", last);
130 err = tplg_save_printf(dst, pfx, "access [\n");
131 if (err < 0)
132 return err;
133 access = hdr->access;
134 for (j = 0; j < ARRAY_SIZE(ctl_access); j++) {
135 cval = ctl_access[j].value;
136 if ((access & cval) == cval) {
137 err = tplg_save_printf(dst, pfx, "\t%s\n",
138 ctl_access[j].name);
139 if (err < 0)
140 return err;
141 access &= ~cval;
142 }
143 }
144 return tplg_save_printf(dst, pfx, "]\n");
145 }
146
147 /* copy referenced TLV to the mixer control */
copy_tlv(struct tplg_elem *elem, struct tplg_elem *ref)148 static int copy_tlv(struct tplg_elem *elem, struct tplg_elem *ref)
149 {
150 struct snd_soc_tplg_mixer_control *mixer_ctrl = elem->mixer_ctrl;
151 struct snd_soc_tplg_ctl_tlv *tlv = ref->tlv;
152
153 tplg_dbg("TLV '%s' used by '%s", ref->id, elem->id);
154
155 /* TLV has a fixed size */
156 mixer_ctrl->hdr.tlv = *tlv;
157 return 0;
158 }
159
160 /* check referenced TLV for a mixer control */
tplg_build_mixer_control(snd_tplg_t *tplg, struct tplg_elem *elem)161 static int tplg_build_mixer_control(snd_tplg_t *tplg,
162 struct tplg_elem *elem)
163 {
164 struct tplg_ref *ref;
165 struct list_head *base, *pos;
166 int err = 0;
167
168 base = &elem->ref_list;
169
170 /* for each ref in this control elem */
171 list_for_each(pos, base) {
172
173 ref = list_entry(pos, struct tplg_ref, list);
174 if (ref->elem)
175 continue;
176
177 if (ref->type == SND_TPLG_TYPE_TLV) {
178 ref->elem = tplg_elem_lookup(&tplg->tlv_list,
179 ref->id, SND_TPLG_TYPE_TLV, elem->index);
180 if (ref->elem)
181 err = copy_tlv(elem, ref->elem);
182
183 } else if (ref->type == SND_TPLG_TYPE_DATA) {
184 err = tplg_copy_data(tplg, elem, ref);
185 if (err < 0)
186 return err;
187 }
188
189 if (!ref->elem) {
190 SNDERR("cannot find '%s' referenced by"
191 " control '%s'", ref->id, elem->id);
192 return -EINVAL;
193 } else if (err < 0)
194 return err;
195 }
196
197 return 0;
198 }
199
copy_enum_texts(struct tplg_elem *enum_elem, struct tplg_elem *ref_elem)200 static void copy_enum_texts(struct tplg_elem *enum_elem,
201 struct tplg_elem *ref_elem)
202 {
203 struct snd_soc_tplg_enum_control *ec = enum_elem->enum_ctrl;
204 struct tplg_texts *texts = ref_elem->texts;
205
206 memcpy(ec->texts, texts->items,
207 SND_SOC_TPLG_NUM_TEXTS * SNDRV_CTL_ELEM_ID_NAME_MAXLEN);
208 ec->items += texts->num_items;
209 }
210
211 /* check referenced text for a enum control */
tplg_build_enum_control(snd_tplg_t *tplg, struct tplg_elem *elem)212 static int tplg_build_enum_control(snd_tplg_t *tplg,
213 struct tplg_elem *elem)
214 {
215 struct tplg_ref *ref;
216 struct list_head *base, *pos;
217 int err;
218
219 base = &elem->ref_list;
220
221 list_for_each(pos, base) {
222
223 ref = list_entry(pos, struct tplg_ref, list);
224 if (ref->elem)
225 continue;
226
227 if (ref->type == SND_TPLG_TYPE_TEXT) {
228 ref->elem = tplg_elem_lookup(&tplg->text_list,
229 ref->id, SND_TPLG_TYPE_TEXT, elem->index);
230 if (ref->elem)
231 copy_enum_texts(elem, ref->elem);
232
233 } else if (ref->type == SND_TPLG_TYPE_DATA) {
234 err = tplg_copy_data(tplg, elem, ref);
235 if (err < 0)
236 return err;
237 }
238 if (!ref->elem) {
239 SNDERR("cannot find '%s' referenced by"
240 " control '%s'", ref->id, elem->id);
241 return -EINVAL;
242 }
243 }
244
245 return 0;
246 }
247
248 /* check referenced private data for a byte control */
tplg_build_bytes_control(snd_tplg_t *tplg, struct tplg_elem *elem)249 static int tplg_build_bytes_control(snd_tplg_t *tplg, struct tplg_elem *elem)
250 {
251 struct tplg_ref *ref;
252 struct list_head *base, *pos;
253 int err;
254
255 base = &elem->ref_list;
256
257 list_for_each(pos, base) {
258
259 ref = list_entry(pos, struct tplg_ref, list);
260 if (ref->elem)
261 continue;
262
263 if (ref->type == SND_TPLG_TYPE_DATA) {
264 err = tplg_copy_data(tplg, elem, ref);
265 if (err < 0)
266 return err;
267 }
268 }
269
270 return 0;
271 }
272
tplg_build_controls(snd_tplg_t *tplg)273 int tplg_build_controls(snd_tplg_t *tplg)
274 {
275 struct list_head *base, *pos;
276 struct tplg_elem *elem;
277 int err = 0;
278
279 base = &tplg->mixer_list;
280 list_for_each(pos, base) {
281
282 elem = list_entry(pos, struct tplg_elem, list);
283 err = tplg_build_mixer_control(tplg, elem);
284 if (err < 0)
285 return err;
286
287 /* add control to manifest */
288 tplg->manifest.control_elems++;
289 }
290
291 base = &tplg->enum_list;
292 list_for_each(pos, base) {
293
294 elem = list_entry(pos, struct tplg_elem, list);
295 err = tplg_build_enum_control(tplg, elem);
296 if (err < 0)
297 return err;
298
299 /* add control to manifest */
300 tplg->manifest.control_elems++;
301 }
302
303 base = &tplg->bytes_ext_list;
304 list_for_each(pos, base) {
305
306 elem = list_entry(pos, struct tplg_elem, list);
307 err = tplg_build_bytes_control(tplg, elem);
308 if (err < 0)
309 return err;
310
311 /* add control to manifest */
312 tplg->manifest.control_elems++;
313 }
314
315 return 0;
316 }
317
318
319 /*
320 * Parse TLV of DBScale type.
321 *
322 * Parse DBScale describing min, step, mute in DB.
323 */
tplg_parse_tlv_dbscale(snd_config_t *cfg, struct tplg_elem *elem)324 static int tplg_parse_tlv_dbscale(snd_config_t *cfg, struct tplg_elem *elem)
325 {
326 snd_config_iterator_t i, next;
327 snd_config_t *n;
328 struct snd_soc_tplg_ctl_tlv *tplg_tlv = elem->tlv;
329 struct snd_soc_tplg_tlv_dbscale *scale;
330 const char *id = NULL;
331 int val;
332
333 tplg_dbg(" scale: %s", elem->id);
334
335 tplg_tlv->size = sizeof(struct snd_soc_tplg_ctl_tlv);
336 tplg_tlv->type = SNDRV_CTL_TLVT_DB_SCALE;
337 scale = &tplg_tlv->scale;
338
339 snd_config_for_each(i, next, cfg) {
340
341 n = snd_config_iterator_entry(i);
342
343 /* get ID */
344 if (snd_config_get_id(n, &id) < 0)
345 return -EINVAL;
346
347 /* get value */
348 if (tplg_get_integer(n, &val, 0))
349 continue;
350
351 tplg_dbg("\t%s = %i", id, val);
352
353 /* get TLV data */
354 if (strcmp(id, "min") == 0)
355 scale->min = val;
356 else if (strcmp(id, "step") == 0)
357 scale->step = val;
358 else if (strcmp(id, "mute") == 0)
359 scale->mute = val;
360 else
361 SNDERR("unknown id '%s'", id);
362 }
363
364 return 0;
365 }
366
367 /* Parse TLV */
tplg_parse_tlv(snd_tplg_t *tplg, snd_config_t *cfg, void *private ATTRIBUTE_UNUSED)368 int tplg_parse_tlv(snd_tplg_t *tplg, snd_config_t *cfg,
369 void *private ATTRIBUTE_UNUSED)
370 {
371 snd_config_iterator_t i, next;
372 snd_config_t *n;
373 const char *id;
374 int err = 0;
375 struct tplg_elem *elem;
376
377 elem = tplg_elem_new_common(tplg, cfg, NULL, SND_TPLG_TYPE_TLV);
378 if (!elem)
379 return -ENOMEM;
380
381 snd_config_for_each(i, next, cfg) {
382
383 n = snd_config_iterator_entry(i);
384 if (snd_config_get_id(n, &id) < 0)
385 continue;
386
387 if (strcmp(id, "scale") == 0) {
388 err = tplg_parse_tlv_dbscale(n, elem);
389 if (err < 0) {
390 SNDERR("failed to DBScale");
391 return err;
392 }
393 continue;
394 }
395 }
396
397 return err;
398 }
399
400 /* save TLV data */
tplg_save_tlv(snd_tplg_t *tplg ATTRIBUTE_UNUSED, struct tplg_elem *elem, struct tplg_buf *dst, const char *pfx)401 int tplg_save_tlv(snd_tplg_t *tplg ATTRIBUTE_UNUSED,
402 struct tplg_elem *elem,
403 struct tplg_buf *dst, const char *pfx)
404 {
405 struct snd_soc_tplg_ctl_tlv *tlv = elem->tlv;
406 struct snd_soc_tplg_tlv_dbscale *scale;
407 int err;
408
409 if (tlv->type != SNDRV_CTL_TLVT_DB_SCALE) {
410 SNDERR("unknown TLV type");
411 return -EINVAL;
412 }
413
414 scale = &tlv->scale;
415 err = tplg_save_printf(dst, NULL, "'%s' {\n", elem->id);
416 if (err >= 0)
417 err = tplg_save_printf(dst, pfx, "\tscale {\n");
418 if (err >= 0 && scale->min)
419 err = tplg_save_printf(dst, pfx, "\t\tmin %i\n", scale->min);
420 if (err >= 0 && scale->step > 0)
421 err = tplg_save_printf(dst, pfx, "\t\tstep %i\n", scale->step);
422 if (err >= 0 && scale->mute > 0)
423 err = tplg_save_printf(dst, pfx, "\t\tmute %i\n", scale->mute);
424 if (err >= 0)
425 err = tplg_save_printf(dst, pfx, "\t}\n");
426 if (err >= 0)
427 err = tplg_save_printf(dst, pfx, "}\n");
428 return err;
429 }
430
431 /* Parse Control Bytes */
tplg_parse_control_bytes(snd_tplg_t *tplg, snd_config_t *cfg, void *private ATTRIBUTE_UNUSED)432 int tplg_parse_control_bytes(snd_tplg_t *tplg,
433 snd_config_t *cfg,
434 void *private ATTRIBUTE_UNUSED)
435 {
436 struct snd_soc_tplg_bytes_control *be;
437 struct tplg_elem *elem;
438 snd_config_iterator_t i, next;
439 snd_config_t *n;
440 const char *id, *val = NULL;
441 int err, ival;
442 bool access_set = false, tlv_set = false;
443
444 elem = tplg_elem_new_common(tplg, cfg, NULL, SND_TPLG_TYPE_BYTES);
445 if (!elem)
446 return -ENOMEM;
447
448 be = elem->bytes_ext;
449 be->size = elem->size;
450 snd_strlcpy(be->hdr.name, elem->id, SNDRV_CTL_ELEM_ID_NAME_MAXLEN);
451 be->hdr.type = SND_SOC_TPLG_TYPE_BYTES;
452
453 tplg_dbg(" Control Bytes: %s", elem->id);
454
455 snd_config_for_each(i, next, cfg) {
456 n = snd_config_iterator_entry(i);
457 if (snd_config_get_id(n, &id) < 0)
458 continue;
459
460 /* skip comments */
461 if (strcmp(id, "comment") == 0)
462 continue;
463 if (id[0] == '#')
464 continue;
465
466 if (strcmp(id, "base") == 0) {
467 if (tplg_get_integer(n, &ival, 0))
468 return -EINVAL;
469
470 be->base = ival;
471 tplg_dbg("\t%s: %d", id, be->base);
472 continue;
473 }
474
475 if (strcmp(id, "num_regs") == 0) {
476 if (tplg_get_integer(n, &ival, 0))
477 return -EINVAL;
478
479 be->num_regs = ival;
480 tplg_dbg("\t%s: %d", id, be->num_regs);
481 continue;
482 }
483
484 if (strcmp(id, "max") == 0) {
485 if (tplg_get_integer(n, &ival, 0))
486 return -EINVAL;
487
488 be->max = ival;
489 tplg_dbg("\t%s: %d", id, be->max);
490 continue;
491 }
492
493 if (strcmp(id, "mask") == 0) {
494 if (tplg_get_integer(n, &ival, 16))
495 return -EINVAL;
496
497 be->mask = ival;
498 tplg_dbg("\t%s: %d", id, be->mask);
499 continue;
500 }
501
502 if (strcmp(id, "data") == 0) {
503 err = tplg_parse_refs(n, elem, SND_TPLG_TYPE_DATA);
504 if (err < 0)
505 return err;
506 continue;
507 }
508
509 if (strcmp(id, "tlv") == 0) {
510 if (snd_config_get_string(n, &val) < 0)
511 return -EINVAL;
512
513 err = tplg_ref_add(elem, SND_TPLG_TYPE_TLV, val);
514 if (err < 0)
515 return err;
516
517 tlv_set = true;
518 tplg_dbg("\t%s: %s", id, val);
519 continue;
520 }
521
522 if (strcmp(id, "ops") == 0) {
523 err = tplg_parse_compound(tplg, n, tplg_parse_ops,
524 &be->hdr);
525 if (err < 0)
526 return err;
527 continue;
528 }
529
530 if (strcmp(id, "extops") == 0) {
531 err = tplg_parse_compound(tplg, n, tplg_parse_ext_ops,
532 be);
533 if (err < 0)
534 return err;
535 continue;
536 }
537
538 if (strcmp(id, "access") == 0) {
539 err = parse_access(cfg, &be->hdr);
540 if (err < 0)
541 return err;
542 access_set = true;
543 continue;
544 }
545 }
546
547 /* set CTL access to default values if none are provided */
548 if (!access_set) {
549
550 be->hdr.access = SNDRV_CTL_ELEM_ACCESS_READWRITE;
551 if (tlv_set)
552 be->hdr.access |= SNDRV_CTL_ELEM_ACCESS_TLV_READ;
553 }
554
555 return 0;
556 }
557
558 /* save control bytes */
tplg_save_control_bytes(snd_tplg_t *tplg ATTRIBUTE_UNUSED, struct tplg_elem *elem, struct tplg_buf *dst, const char *pfx)559 int tplg_save_control_bytes(snd_tplg_t *tplg ATTRIBUTE_UNUSED,
560 struct tplg_elem *elem,
561 struct tplg_buf *dst, const char *pfx)
562 {
563 struct snd_soc_tplg_bytes_control *be = elem->bytes_ext;
564 char pfx2[16];
565 int err;
566
567 if (!be)
568 return 0;
569
570 snprintf(pfx2, sizeof(pfx2), "%s\t", pfx ?: "");
571 err = tplg_save_printf(dst, NULL, "'%s' {\n", elem->id);
572 if (err < 0)
573 return err;
574 if (err >= 0 && elem->index > 0)
575 err = tplg_save_printf(dst, pfx, "\tindex %u\n", elem->index);
576 if (err >= 0 && be->base > 0)
577 err = tplg_save_printf(dst, pfx, "\tbase %u\n", be->base);
578 if (err >= 0 && be->num_regs > 0)
579 err = tplg_save_printf(dst, pfx, "\tnum_regs %u\n", be->num_regs);
580 if (err >= 0 && be->max > 0)
581 err = tplg_save_printf(dst, pfx, "\tmax %u\n", be->max);
582 if (err >= 0 && be->mask > 0)
583 err = tplg_save_printf(dst, pfx, "\tmask %u\n", be->mask);
584 if (err >= 0)
585 err = tplg_save_ops(tplg, &be->hdr, dst, pfx2);
586 if (err >= 0)
587 err = tplg_save_ext_ops(tplg, be, dst, pfx2);
588 if (err >= 0)
589 err = tplg_save_access(tplg, &be->hdr, dst, pfx2);
590 if (err >= 0)
591 err = tplg_save_refs(tplg, elem, SND_TPLG_TYPE_TLV,
592 "tlv", dst, pfx2);
593 if (err >= 0)
594 err = tplg_save_refs(tplg, elem, SND_TPLG_TYPE_DATA,
595 "data", dst, pfx2);
596 if (err >= 0)
597 err = tplg_save_printf(dst, pfx, "}\n");
598 return err;
599 }
600
601 /* Parse Control Enums. */
tplg_parse_control_enum(snd_tplg_t *tplg, snd_config_t *cfg, void *private ATTRIBUTE_UNUSED)602 int tplg_parse_control_enum(snd_tplg_t *tplg, snd_config_t *cfg,
603 void *private ATTRIBUTE_UNUSED)
604 {
605 struct snd_soc_tplg_enum_control *ec;
606 struct tplg_elem *elem;
607 snd_config_iterator_t i, next;
608 snd_config_t *n;
609 const char *id, *val = NULL;
610 int err, j;
611 bool access_set = false;
612
613 elem = tplg_elem_new_common(tplg, cfg, NULL, SND_TPLG_TYPE_ENUM);
614 if (!elem)
615 return -ENOMEM;
616
617 ec = elem->enum_ctrl;
618 snd_strlcpy(ec->hdr.name, elem->id, SNDRV_CTL_ELEM_ID_NAME_MAXLEN);
619 ec->hdr.type = SND_SOC_TPLG_TYPE_ENUM;
620 ec->size = elem->size;
621 tplg->channel_idx = 0;
622
623 /* set channel reg to default state */
624 for (j = 0; j < SND_SOC_TPLG_MAX_CHAN; j++) {
625 ec->channel[j].reg = -1;
626 }
627
628 tplg_dbg(" Control Enum: %s", elem->id);
629
630 snd_config_for_each(i, next, cfg) {
631
632 n = snd_config_iterator_entry(i);
633 if (snd_config_get_id(n, &id) < 0)
634 continue;
635
636 /* skip comments */
637 if (strcmp(id, "comment") == 0)
638 continue;
639 if (id[0] == '#')
640 continue;
641
642 if (strcmp(id, "texts") == 0) {
643 if (snd_config_get_string(n, &val) < 0)
644 return -EINVAL;
645
646 tplg_ref_add(elem, SND_TPLG_TYPE_TEXT, val);
647 tplg_dbg("\t%s: %s", id, val);
648 continue;
649 }
650
651 if (strcmp(id, "channel") == 0) {
652 if (ec->num_channels >= SND_SOC_TPLG_MAX_CHAN) {
653 SNDERR("too many channels %s", elem->id);
654 return -EINVAL;
655 }
656
657 err = tplg_parse_compound(tplg, n, tplg_parse_channel,
658 ec->channel);
659 if (err < 0)
660 return err;
661
662 ec->num_channels = tplg->channel_idx;
663 continue;
664 }
665
666 if (strcmp(id, "ops") == 0) {
667 err = tplg_parse_compound(tplg, n, tplg_parse_ops,
668 &ec->hdr);
669 if (err < 0)
670 return err;
671 continue;
672 }
673
674 if (strcmp(id, "data") == 0) {
675 err = tplg_parse_refs(n, elem, SND_TPLG_TYPE_DATA);
676 if (err < 0)
677 return err;
678 continue;
679 }
680
681 if (strcmp(id, "access") == 0) {
682 err = parse_access(cfg, &ec->hdr);
683 if (err < 0)
684 return err;
685 access_set = true;
686 continue;
687 }
688 }
689
690 /* set CTL access to default values if none are provided */
691 if (!access_set) {
692 ec->hdr.access = SNDRV_CTL_ELEM_ACCESS_READWRITE;
693 }
694
695 return 0;
696 }
697
698 /* save control eunm */
tplg_save_control_enum(snd_tplg_t *tplg ATTRIBUTE_UNUSED, struct tplg_elem *elem, struct tplg_buf *dst, const char *pfx)699 int tplg_save_control_enum(snd_tplg_t *tplg ATTRIBUTE_UNUSED,
700 struct tplg_elem *elem,
701 struct tplg_buf *dst, const char *pfx)
702 {
703 struct snd_soc_tplg_enum_control *ec = elem->enum_ctrl;
704 char pfx2[16];
705 int err;
706
707 if (!ec)
708 return 0;
709
710 snprintf(pfx2, sizeof(pfx2), "%s\t", pfx ?: "");
711 err = tplg_save_printf(dst, NULL, "'%s' {\n", elem->id);
712 if (err < 0)
713 return err;
714 if (err >= 0 && elem->index > 0)
715 err = tplg_save_printf(dst, pfx, "\tindex %u\n", elem->index);
716 if (err >= 0)
717 err = tplg_save_refs(tplg, elem, SND_TPLG_TYPE_TEXT,
718 "texts", dst, pfx2);
719 if (err >= 0)
720 err = tplg_save_channels(tplg, ec->channel, ec->num_channels,
721 dst, pfx2);
722 if (err >= 0)
723 err = tplg_save_ops(tplg, &ec->hdr, dst, pfx2);
724 if (err >= 0)
725 err = tplg_save_access(tplg, &ec->hdr, dst, pfx2);
726 if (err >= 0)
727 err = tplg_save_refs(tplg, elem, SND_TPLG_TYPE_DATA,
728 "data", dst, pfx2);
729 if (err >= 0)
730 err = tplg_save_printf(dst, pfx, "}\n");
731 return err;
732 }
733
734 /* Parse Controls.
735 *
736 * Mixer control. Supports multiple channels.
737 */
tplg_parse_control_mixer(snd_tplg_t *tplg, snd_config_t *cfg, void *private ATTRIBUTE_UNUSED)738 int tplg_parse_control_mixer(snd_tplg_t *tplg,
739 snd_config_t *cfg,
740 void *private ATTRIBUTE_UNUSED)
741 {
742 struct snd_soc_tplg_mixer_control *mc;
743 struct tplg_elem *elem;
744 snd_config_iterator_t i, next;
745 snd_config_t *n;
746 const char *id, *val = NULL;
747 int err, j, ival;
748 bool access_set = false, tlv_set = false;
749
750 elem = tplg_elem_new_common(tplg, cfg, NULL, SND_TPLG_TYPE_MIXER);
751 if (!elem)
752 return -ENOMEM;
753
754 /* init new mixer */
755 mc = elem->mixer_ctrl;
756 snd_strlcpy(mc->hdr.name, elem->id, SNDRV_CTL_ELEM_ID_NAME_MAXLEN);
757 mc->hdr.type = SND_SOC_TPLG_TYPE_MIXER;
758 mc->size = elem->size;
759 tplg->channel_idx = 0;
760
761 /* set channel reg to default state */
762 for (j = 0; j < SND_SOC_TPLG_MAX_CHAN; j++)
763 mc->channel[j].reg = -1;
764
765 tplg_dbg(" Control Mixer: %s", elem->id);
766
767 /* giterate trough each mixer elment */
768 snd_config_for_each(i, next, cfg) {
769 n = snd_config_iterator_entry(i);
770 if (snd_config_get_id(n, &id) < 0)
771 continue;
772
773 /* skip comments */
774 if (strcmp(id, "comment") == 0)
775 continue;
776 if (id[0] == '#')
777 continue;
778
779 if (strcmp(id, "channel") == 0) {
780 if (mc->num_channels >= SND_SOC_TPLG_MAX_CHAN) {
781 SNDERR("too many channels %s", elem->id);
782 return -EINVAL;
783 }
784
785 err = tplg_parse_compound(tplg, n, tplg_parse_channel,
786 mc->channel);
787 if (err < 0)
788 return err;
789
790 mc->num_channels = tplg->channel_idx;
791 continue;
792 }
793
794 if (strcmp(id, "max") == 0) {
795 if (tplg_get_integer(n, &ival, 0))
796 return -EINVAL;
797
798 mc->max = ival;
799 tplg_dbg("\t%s: %d", id, mc->max);
800 continue;
801 }
802
803 if (strcmp(id, "invert") == 0) {
804 ival = snd_config_get_bool(n);
805 if (ival < 0)
806 return -EINVAL;
807 mc->invert = ival;
808
809 tplg_dbg("\t%s: %d", id, mc->invert);
810 continue;
811 }
812
813 if (strcmp(id, "ops") == 0) {
814 err = tplg_parse_compound(tplg, n, tplg_parse_ops,
815 &mc->hdr);
816 if (err < 0)
817 return err;
818 continue;
819 }
820
821 if (strcmp(id, "tlv") == 0) {
822 if (snd_config_get_string(n, &val) < 0)
823 return -EINVAL;
824
825 err = tplg_ref_add(elem, SND_TPLG_TYPE_TLV, val);
826 if (err < 0)
827 return err;
828
829 tlv_set = true;
830 tplg_dbg("\t%s: %s", id, val);
831 continue;
832 }
833
834 if (strcmp(id, "data") == 0) {
835 err = tplg_parse_refs(n, elem, SND_TPLG_TYPE_DATA);
836 if (err < 0)
837 return err;
838 continue;
839 }
840
841 if (strcmp(id, "access") == 0) {
842 err = parse_access(cfg, &mc->hdr);
843 if (err < 0)
844 return err;
845 access_set = true;
846 continue;
847 }
848 }
849
850 /* set CTL access to default values if none are provided */
851 if (!access_set) {
852
853 mc->hdr.access = SNDRV_CTL_ELEM_ACCESS_READWRITE;
854 if (tlv_set)
855 mc->hdr.access |= SNDRV_CTL_ELEM_ACCESS_TLV_READ;
856 }
857
858 return 0;
859 }
860
tplg_save_control_mixer(snd_tplg_t *tplg ATTRIBUTE_UNUSED, struct tplg_elem *elem, struct tplg_buf *dst, const char *pfx)861 int tplg_save_control_mixer(snd_tplg_t *tplg ATTRIBUTE_UNUSED,
862 struct tplg_elem *elem,
863 struct tplg_buf *dst, const char *pfx)
864 {
865 struct snd_soc_tplg_mixer_control *mc = elem->mixer_ctrl;
866 char pfx2[16];
867 int err;
868
869 if (!mc)
870 return 0;
871 err = tplg_save_printf(dst, NULL, "'%s' {\n", elem->id);
872 if (err < 0)
873 return err;
874 snprintf(pfx2, sizeof(pfx2), "%s\t", pfx ?: "");
875 if (err >= 0 && elem->index > 0)
876 err = tplg_save_printf(dst, pfx, "\tindex %u\n", elem->index);
877 if (err >= 0)
878 err = tplg_save_channels(tplg, mc->channel, mc->num_channels,
879 dst, pfx2);
880 if (err >= 0 && mc->max > 0)
881 err = tplg_save_printf(dst, pfx, "\tmax %u\n", mc->max);
882 if (err >= 0 && mc->invert > 0)
883 err = tplg_save_printf(dst, pfx, "\tinvert 1\n");
884 if (err >= 0 && mc->invert > 0)
885 err = tplg_save_printf(dst, pfx, "\tinvert 1\n");
886 if (err >= 0)
887 err = tplg_save_ops(tplg, &mc->hdr, dst, pfx2);
888 if (err >= 0)
889 err = tplg_save_access(tplg, &mc->hdr, dst, pfx2);
890 if (err >= 0)
891 err = tplg_save_refs(tplg, elem, SND_TPLG_TYPE_TLV,
892 "tlv", dst, pfx2);
893 if (err >= 0)
894 err = tplg_save_refs(tplg, elem, SND_TPLG_TYPE_DATA,
895 "data", dst, pfx2);
896 if (err >= 0)
897 err = tplg_save_printf(dst, pfx, "}\n");
898 return err;
899 }
900
init_ctl_hdr(snd_tplg_t *tplg, struct tplg_elem *parent, struct snd_soc_tplg_ctl_hdr *hdr, struct snd_tplg_ctl_template *t)901 static int init_ctl_hdr(snd_tplg_t *tplg,
902 struct tplg_elem *parent,
903 struct snd_soc_tplg_ctl_hdr *hdr,
904 struct snd_tplg_ctl_template *t)
905 {
906 struct tplg_elem *elem;
907 int err;
908
909 hdr->size = sizeof(struct snd_soc_tplg_ctl_hdr);
910 hdr->type = t->type;
911
912 snd_strlcpy(hdr->name, t->name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN);
913
914 /* clean up access flag */
915 if (t->access == 0)
916 t->access = SNDRV_CTL_ELEM_ACCESS_READWRITE;
917 t->access &= (SNDRV_CTL_ELEM_ACCESS_READWRITE |
918 SNDRV_CTL_ELEM_ACCESS_VOLATILE |
919 SNDRV_CTL_ELEM_ACCESS_INACTIVE |
920 SNDRV_CTL_ELEM_ACCESS_TLV_READWRITE |
921 SNDRV_CTL_ELEM_ACCESS_TLV_COMMAND |
922 SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK);
923
924 hdr->access = t->access;
925 hdr->ops.get = t->ops.get;
926 hdr->ops.put = t->ops.put;
927 hdr->ops.info = t->ops.info;
928
929 /* TLV */
930 if (hdr->access & SNDRV_CTL_ELEM_ACCESS_TLV_READWRITE
931 && !(hdr->access & SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK)) {
932
933 struct snd_tplg_tlv_template *tlvt = t->tlv;
934 struct snd_soc_tplg_ctl_tlv *tlv;
935 struct snd_tplg_tlv_dbscale_template *scalet;
936 struct snd_soc_tplg_tlv_dbscale *scale;
937
938 if (!tlvt) {
939 SNDERR("missing TLV data");
940 return -EINVAL;
941 }
942
943 elem = tplg_elem_new_common(tplg, NULL, parent->id,
944 SND_TPLG_TYPE_TLV);
945 if (!elem)
946 return -ENOMEM;
947
948 tlv = elem->tlv;
949
950 err = tplg_ref_add(parent, SND_TPLG_TYPE_TLV, parent->id);
951 if (err < 0)
952 return err;
953
954 tlv->size = sizeof(struct snd_soc_tplg_ctl_tlv);
955 tlv->type = tlvt->type;
956
957 switch (tlvt->type) {
958 case SNDRV_CTL_TLVT_DB_SCALE:
959 scalet = container_of(tlvt,
960 struct snd_tplg_tlv_dbscale_template, hdr);
961 scale = &tlv->scale;
962 scale->min = scalet->min;
963 scale->step = scalet->step;
964 scale->mute = scalet->mute;
965 break;
966
967 /* TODO: add support for other TLV types */
968 default:
969 SNDERR("unsupported TLV type %d", tlv->type);
970 break;
971 }
972 }
973
974 return 0;
975 }
976
tplg_add_mixer(snd_tplg_t *tplg, struct snd_tplg_mixer_template *mixer, struct tplg_elem **e)977 int tplg_add_mixer(snd_tplg_t *tplg, struct snd_tplg_mixer_template *mixer,
978 struct tplg_elem **e)
979 {
980 struct snd_soc_tplg_mixer_control *mc;
981 struct snd_soc_tplg_private *priv;
982 struct tplg_elem *elem;
983 int ret, i, num_channels;
984
985 tplg_dbg(" Control Mixer: %s", mixer->hdr.name);
986
987 if (mixer->hdr.type != SND_SOC_TPLG_TYPE_MIXER) {
988 SNDERR("invalid mixer type %d", mixer->hdr.type);
989 return -EINVAL;
990 }
991
992 elem = tplg_elem_new_common(tplg, NULL, mixer->hdr.name,
993 SND_TPLG_TYPE_MIXER);
994 if (!elem)
995 return -ENOMEM;
996
997 /* init new mixer */
998 mc = elem->mixer_ctrl;
999 mc->size = elem->size;
1000 ret = init_ctl_hdr(tplg, elem, &mc->hdr, &mixer->hdr);
1001 if (ret < 0) {
1002 tplg_elem_free(elem);
1003 return ret;
1004 }
1005
1006 mc->min = mixer->min;
1007 mc->max = mixer->max;
1008 mc->platform_max = mixer->platform_max;
1009 mc->invert = mixer->invert;
1010
1011 /* set channel reg to default state */
1012 for (i = 0; i < SND_SOC_TPLG_MAX_CHAN; i++)
1013 mc->channel[i].reg = -1;
1014
1015 num_channels = mixer->map ? mixer->map->num_channels : 0;
1016 mc->num_channels = num_channels;
1017
1018 for (i = 0; i < num_channels; i++) {
1019 struct snd_tplg_channel_elem *channel = &mixer->map->channel[i];
1020
1021 mc->channel[i].size = sizeof(mc->channel[0]);
1022 mc->channel[i].reg = channel->reg;
1023 mc->channel[i].shift = channel->shift;
1024 mc->channel[i].id = channel->id;
1025 }
1026
1027 /* priv data */
1028 priv = mixer->priv;
1029 if (priv && priv->size > 0) {
1030 ret = tplg_add_data(tplg, elem, priv,
1031 sizeof(*priv) + priv->size);
1032 if (ret < 0)
1033 return ret;
1034 }
1035
1036 if (e)
1037 *e = elem;
1038 return 0;
1039 }
1040
tplg_add_enum(snd_tplg_t *tplg, struct snd_tplg_enum_template *enum_ctl, struct tplg_elem **e)1041 int tplg_add_enum(snd_tplg_t *tplg, struct snd_tplg_enum_template *enum_ctl,
1042 struct tplg_elem **e)
1043 {
1044 struct snd_soc_tplg_enum_control *ec;
1045 struct snd_soc_tplg_private *priv;
1046 struct tplg_elem *elem;
1047 int ret, i, num_items, num_channels;
1048
1049 tplg_dbg(" Control Enum: %s", enum_ctl->hdr.name);
1050
1051 if (enum_ctl->hdr.type != SND_SOC_TPLG_TYPE_ENUM) {
1052 SNDERR("invalid enum type %d", enum_ctl->hdr.type);
1053 return -EINVAL;
1054 }
1055
1056 elem = tplg_elem_new_common(tplg, NULL, enum_ctl->hdr.name,
1057 SND_TPLG_TYPE_ENUM);
1058 if (!elem)
1059 return -ENOMEM;
1060
1061 ec = elem->enum_ctrl;
1062 ec->size = elem->size;
1063 ret = init_ctl_hdr(tplg, elem, &ec->hdr, &enum_ctl->hdr);
1064 if (ret < 0) {
1065 tplg_elem_free(elem);
1066 return ret;
1067 }
1068
1069 num_items = enum_ctl->items < SND_SOC_TPLG_NUM_TEXTS ?
1070 enum_ctl->items : SND_SOC_TPLG_NUM_TEXTS;
1071 ec->items = num_items;
1072 ec->mask = enum_ctl->mask;
1073 ec->count = enum_ctl->items;
1074
1075 /* set channel reg to default state */
1076 for (i = 0; i < SND_SOC_TPLG_MAX_CHAN; i++)
1077 ec->channel[i].reg = -1;
1078
1079 num_channels = enum_ctl->map ? enum_ctl->map->num_channels : 0;
1080 ec->num_channels = num_channels;
1081
1082 for (i = 0; i < num_channels; i++) {
1083 struct snd_tplg_channel_elem *channel = &enum_ctl->map->channel[i];
1084
1085 ec->channel[i].size = sizeof(ec->channel[0]);
1086 ec->channel[i].reg = channel->reg;
1087 ec->channel[i].shift = channel->shift;
1088 ec->channel[i].id = channel->id;
1089 }
1090
1091 if (enum_ctl->texts != NULL) {
1092 struct tplg_elem *texts = tplg_elem_new_common(tplg, NULL,
1093 enum_ctl->hdr.name, SND_TPLG_TYPE_TEXT);
1094
1095 texts->texts->num_items = num_items;
1096 for (i = 0; i < num_items; i++) {
1097 if (!enum_ctl->texts[i])
1098 continue;
1099 snd_strlcpy(ec->texts[i], enum_ctl->texts[i],
1100 SNDRV_CTL_ELEM_ID_NAME_MAXLEN);
1101 snd_strlcpy(texts->texts->items[i], enum_ctl->texts[i],
1102 SNDRV_CTL_ELEM_ID_NAME_MAXLEN);
1103 }
1104 tplg_ref_add(elem, SND_TPLG_TYPE_TEXT, enum_ctl->hdr.name);
1105 }
1106
1107 if (enum_ctl->values != NULL) {
1108 for (i = 0; i < num_items; i++) {
1109 if (enum_ctl->values[i] == NULL)
1110 continue;
1111
1112 memcpy(&ec->values[i * sizeof(int) * ENUM_VAL_SIZE],
1113 enum_ctl->values[i],
1114 sizeof(int) * ENUM_VAL_SIZE);
1115 }
1116 }
1117
1118 /* priv data */
1119 priv = enum_ctl->priv;
1120 if (priv && priv->size > 0) {
1121 ret = tplg_add_data(tplg, elem, priv,
1122 sizeof(*priv) + priv->size);
1123 if (ret < 0)
1124 return ret;
1125 }
1126
1127 if (e)
1128 *e = elem;
1129 return 0;
1130 }
1131
tplg_add_bytes(snd_tplg_t *tplg, struct snd_tplg_bytes_template *bytes_ctl, struct tplg_elem **e)1132 int tplg_add_bytes(snd_tplg_t *tplg, struct snd_tplg_bytes_template *bytes_ctl,
1133 struct tplg_elem **e)
1134 {
1135 struct snd_soc_tplg_bytes_control *be;
1136 struct snd_soc_tplg_private *priv;
1137 struct tplg_elem *elem;
1138 int ret;
1139
1140 tplg_dbg(" Control Bytes: %s", bytes_ctl->hdr.name);
1141
1142 if (bytes_ctl->hdr.type != SND_SOC_TPLG_TYPE_BYTES) {
1143 SNDERR("invalid bytes type %d", bytes_ctl->hdr.type);
1144 return -EINVAL;
1145 }
1146
1147 elem = tplg_elem_new_common(tplg, NULL, bytes_ctl->hdr.name,
1148 SND_TPLG_TYPE_BYTES);
1149 if (!elem)
1150 return -ENOMEM;
1151
1152 be = elem->bytes_ext;
1153 be->size = elem->size;
1154 ret = init_ctl_hdr(tplg, elem, &be->hdr, &bytes_ctl->hdr);
1155 if (ret < 0) {
1156 tplg_elem_free(elem);
1157 return ret;
1158 }
1159
1160 be->max = bytes_ctl->max;
1161 be->mask = bytes_ctl->mask;
1162 be->base = bytes_ctl->base;
1163 be->num_regs = bytes_ctl->num_regs;
1164 be->ext_ops.put = bytes_ctl->ext_ops.put;
1165 be->ext_ops.get = bytes_ctl->ext_ops.get;
1166
1167 /* priv data */
1168 priv = bytes_ctl->priv;
1169 if (priv && priv->size > 0) {
1170 ret = tplg_add_data(tplg, elem, priv,
1171 sizeof(*priv) + priv->size);
1172 if (ret < 0)
1173 return ret;
1174 }
1175
1176 /* check on TLV bytes control */
1177 if (be->hdr.access & SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK) {
1178 if ((be->hdr.access & SNDRV_CTL_ELEM_ACCESS_TLV_READWRITE)
1179 != SNDRV_CTL_ELEM_ACCESS_TLV_READWRITE) {
1180 SNDERR("Invalid TLV bytes control access 0x%x",
1181 be->hdr.access);
1182 tplg_elem_free(elem);
1183 return -EINVAL;
1184 }
1185
1186 if (!be->max) {
1187 tplg_elem_free(elem);
1188 return -EINVAL;
1189 }
1190 }
1191
1192 if (e)
1193 *e = elem;
1194 return 0;
1195 }
1196
tplg_add_mixer_object(snd_tplg_t *tplg, snd_tplg_obj_template_t *t)1197 int tplg_add_mixer_object(snd_tplg_t *tplg, snd_tplg_obj_template_t *t)
1198 {
1199 return tplg_add_mixer(tplg, t->mixer, NULL);
1200 }
1201
tplg_add_enum_object(snd_tplg_t *tplg, snd_tplg_obj_template_t *t)1202 int tplg_add_enum_object(snd_tplg_t *tplg, snd_tplg_obj_template_t *t)
1203 {
1204 return tplg_add_enum(tplg, t->enum_ctl, NULL);
1205 }
1206
tplg_add_bytes_object(snd_tplg_t *tplg, snd_tplg_obj_template_t *t)1207 int tplg_add_bytes_object(snd_tplg_t *tplg, snd_tplg_obj_template_t *t)
1208 {
1209 return tplg_add_bytes(tplg, t->bytes_ctl, NULL);
1210 }
1211
tplg_decode_control_mixer1(snd_tplg_t *tplg, struct list_head *heap, struct snd_tplg_mixer_template *mt, size_t pos, void *bin, size_t size)1212 int tplg_decode_control_mixer1(snd_tplg_t *tplg,
1213 struct list_head *heap,
1214 struct snd_tplg_mixer_template *mt,
1215 size_t pos,
1216 void *bin, size_t size)
1217 {
1218 struct snd_soc_tplg_mixer_control *mc = bin;
1219 struct snd_tplg_channel_map_template *map;
1220 struct snd_tplg_tlv_dbscale_template *db;
1221 int i;
1222
1223 if (size < sizeof(*mc)) {
1224 SNDERR("mixer: small size %d", size);
1225 return -EINVAL;
1226 }
1227
1228 tplg_log(tplg, 'D', pos, "mixer: size %d TLV size %d private size %d",
1229 mc->size, mc->hdr.tlv.size, mc->priv.size);
1230 if (size != mc->size + mc->priv.size) {
1231 SNDERR("mixer: unexpected element size %d", size);
1232 return -EINVAL;
1233 }
1234
1235 memset(mt, 0, sizeof(*mt));
1236 mt->hdr.type = mc->hdr.type;
1237 mt->hdr.name = mc->hdr.name;
1238 mt->hdr.access = mc->hdr.access;
1239 mt->hdr.ops.get = mc->hdr.ops.get;
1240 mt->hdr.ops.put = mc->hdr.ops.put;
1241 mt->hdr.ops.info = mc->hdr.ops.info;
1242 mt->min = mc->min;
1243 mt->max = mc->max;
1244 mt->platform_max = mc->platform_max;
1245 tplg_log(tplg, 'D', pos, "mixer: name '%s' access 0x%x",
1246 mt->hdr.name, mt->hdr.access);
1247 if (mc->num_channels > 0) {
1248 map = tplg_calloc(heap, sizeof(*map));
1249 map->num_channels = mc->num_channels;
1250 for (i = 0; i < map->num_channels; i++) {
1251 map->channel[i].reg = mc->channel[i].reg;
1252 map->channel[i].shift = mc->channel[i].shift;
1253 map->channel[i].id = mc->channel[i].id;
1254 }
1255 mt->map = map;
1256 }
1257 if (mc->hdr.tlv.size == 0) {
1258 /* nothing */
1259 } else if (mc->hdr.tlv.size == sizeof(struct snd_soc_tplg_ctl_tlv)) {
1260 if (mc->hdr.tlv.type != SNDRV_CTL_TLVT_DB_SCALE) {
1261 SNDERR("mixer: unknown TLV type %d",
1262 mc->hdr.tlv.type);
1263 return -EINVAL;
1264 }
1265 db = tplg_calloc(heap, sizeof(*db));
1266 if (db == NULL)
1267 return -ENOMEM;
1268 mt->hdr.tlv_scale = db;
1269 db->hdr.type = mc->hdr.tlv.type;
1270 db->min = mc->hdr.tlv.scale.min;
1271 db->step = mc->hdr.tlv.scale.step;
1272 db->mute = mc->hdr.tlv.scale.mute;
1273 tplg_log(tplg, 'D', pos, "mixer: dB scale TLV: min %d step %d mute %d",
1274 db->min, db->step, db->mute);
1275 } else {
1276 SNDERR("mixer: wrong TLV size %d", mc->hdr.tlv.size);
1277 return -EINVAL;
1278 }
1279
1280 mt->priv = &mc->priv;
1281 tplg_log(tplg, 'D', pos + offsetof(struct snd_soc_tplg_mixer_control, priv),
1282 "mixer: private start");
1283 return 0;
1284 }
1285
tplg_decode_control_mixer(snd_tplg_t *tplg, size_t pos, struct snd_soc_tplg_hdr *hdr, void *bin, size_t size)1286 int tplg_decode_control_mixer(snd_tplg_t *tplg,
1287 size_t pos,
1288 struct snd_soc_tplg_hdr *hdr,
1289 void *bin, size_t size)
1290 {
1291 struct list_head heap;
1292 snd_tplg_obj_template_t t;
1293 struct snd_tplg_mixer_template mt;
1294 struct snd_soc_tplg_mixer_control *mc;
1295 size_t size2;
1296 int err;
1297
1298 err = tplg_decode_template(tplg, pos, hdr, &t);
1299 if (err < 0)
1300 return err;
1301
1302 next:
1303 if (size < sizeof(*mc)) {
1304 SNDERR("mixer: small size %d", size);
1305 return -EINVAL;
1306 }
1307 INIT_LIST_HEAD(&heap);
1308 mc = bin;
1309 size2 = mc->size + mc->priv.size;
1310 if (size2 > size) {
1311 SNDERR("mixer: wrong element size (%d, priv %d)",
1312 mc->size, mc->priv.size);
1313 return -EINVAL;
1314 }
1315
1316 err = tplg_decode_control_mixer1(tplg, &heap, &mt, pos, bin, size2);
1317 if (err >= 0) {
1318 t.mixer = &mt;
1319 err = snd_tplg_add_object(tplg, &t);
1320 }
1321 tplg_free(&heap);
1322 if (err < 0)
1323 return err;
1324
1325 bin += size2;
1326 size -= size2;
1327 pos += size2;
1328
1329 if (size > 0)
1330 goto next;
1331
1332 return 0;
1333 }
1334
tplg_decode_control_enum1(snd_tplg_t *tplg, struct list_head *heap, struct snd_tplg_enum_template *et, size_t pos, struct snd_soc_tplg_enum_control *ec)1335 int tplg_decode_control_enum1(snd_tplg_t *tplg,
1336 struct list_head *heap,
1337 struct snd_tplg_enum_template *et,
1338 size_t pos,
1339 struct snd_soc_tplg_enum_control *ec)
1340 {
1341 int i;
1342
1343 if (ec->num_channels > SND_TPLG_MAX_CHAN ||
1344 ec->num_channels > SND_SOC_TPLG_MAX_CHAN) {
1345 SNDERR("enum: unexpected channel count %d", ec->num_channels);
1346 return -EINVAL;
1347 }
1348 if (ec->items > SND_SOC_TPLG_NUM_TEXTS) {
1349 SNDERR("enum: unexpected texts count %d", ec->items);
1350 return -EINVAL;
1351 }
1352
1353 memset(et, 0, sizeof(*et));
1354 et->hdr.type = ec->hdr.type;
1355 et->hdr.name = ec->hdr.name;
1356 et->hdr.access = ec->hdr.access;
1357 et->hdr.ops.get = ec->hdr.ops.get;
1358 et->hdr.ops.put = ec->hdr.ops.put;
1359 et->hdr.ops.info = ec->hdr.ops.info;
1360 et->mask = ec->mask;
1361
1362 if (ec->items > 0) {
1363 et->items = ec->items;
1364 et->texts = tplg_calloc(heap, sizeof(char *) * ec->items);
1365 if (!et->texts)
1366 return -ENOMEM;
1367 for (i = 0; (unsigned int)i < ec->items; i++)
1368 et->texts[i] = ec->texts[i];
1369 }
1370
1371 et->map = tplg_calloc(heap, sizeof(struct snd_tplg_channel_map_template));
1372 if (!et->map)
1373 return -ENOMEM;
1374 et->map->num_channels = ec->num_channels;
1375 for (i = 0; i < et->map->num_channels; i++) {
1376 struct snd_tplg_channel_elem *channel = &et->map->channel[i];
1377
1378 tplg_log(tplg, 'D', pos + ((void *)&ec->channel[i] - (void *)ec),
1379 "enum: channel size %d", ec->channel[i].size);
1380 channel->reg = ec->channel[i].reg;
1381 channel->shift = ec->channel[i].shift;
1382 channel->id = ec->channel[i].id;
1383 }
1384
1385 et->priv = &ec->priv;
1386 return 0;
1387 }
1388
tplg_decode_control_enum(snd_tplg_t *tplg, size_t pos, struct snd_soc_tplg_hdr *hdr, void *bin, size_t size)1389 int tplg_decode_control_enum(snd_tplg_t *tplg,
1390 size_t pos,
1391 struct snd_soc_tplg_hdr *hdr,
1392 void *bin, size_t size)
1393 {
1394 struct list_head heap;
1395 snd_tplg_obj_template_t t;
1396 struct snd_tplg_enum_template et;
1397 struct snd_soc_tplg_enum_control *ec;
1398 size_t size2;
1399 int err;
1400
1401 err = tplg_decode_template(tplg, pos, hdr, &t);
1402 if (err < 0)
1403 return err;
1404
1405 next:
1406 if (size < sizeof(*ec)) {
1407 SNDERR("enum: small size %d", size);
1408 return -EINVAL;
1409 }
1410 INIT_LIST_HEAD(&heap);
1411 ec = bin;
1412 size2 = ec->size + ec->priv.size;
1413 if (size2 > size) {
1414 SNDERR("enum: wrong element size (%d, priv %d)",
1415 ec->size, ec->priv.size);
1416 return -EINVAL;
1417 }
1418
1419 tplg_log(tplg, 'D', pos, "enum: size %d private size %d",
1420 ec->size, ec->priv.size);
1421
1422 err = tplg_decode_control_enum1(tplg, &heap, &et, pos, ec);
1423 if (err >= 0) {
1424 t.enum_ctl = &et;
1425 err = snd_tplg_add_object(tplg, &t);
1426 }
1427 tplg_free(&heap);
1428 if (err < 0)
1429 return err;
1430
1431 bin += size2;
1432 size -= size2;
1433 pos += size2;
1434
1435 if (size > 0)
1436 goto next;
1437
1438 return 0;
1439 }
1440
tplg_decode_control_bytes1(snd_tplg_t *tplg, struct snd_tplg_bytes_template *bt, size_t pos, void *bin, size_t size)1441 int tplg_decode_control_bytes1(snd_tplg_t *tplg,
1442 struct snd_tplg_bytes_template *bt,
1443 size_t pos,
1444 void *bin, size_t size)
1445 {
1446 struct snd_soc_tplg_bytes_control *bc = bin;
1447
1448 if (size < sizeof(*bc)) {
1449 SNDERR("bytes: small size %d", size);
1450 return -EINVAL;
1451 }
1452
1453 tplg_log(tplg, 'D', pos, "control bytes: size %d private size %d",
1454 bc->size, bc->priv.size);
1455 if (size != bc->size + bc->priv.size) {
1456 SNDERR("bytes: unexpected element size %d", size);
1457 return -EINVAL;
1458 }
1459
1460 memset(bt, 0, sizeof(*bt));
1461 bt->hdr.type = bc->hdr.type;
1462 bt->hdr.name = bc->hdr.name;
1463 bt->hdr.access = bc->hdr.access;
1464 bt->hdr.ops.get = bc->hdr.ops.get;
1465 bt->hdr.ops.put = bc->hdr.ops.put;
1466 bt->hdr.ops.info = bc->hdr.ops.info;
1467 bt->max = bc->max;
1468 bt->mask = bc->mask;
1469 bt->base = bc->base;
1470 bt->num_regs = bc->num_regs;
1471 bt->ext_ops.get = bc->ext_ops.get;
1472 bt->ext_ops.put = bc->ext_ops.put;
1473 bt->ext_ops.info = bc->ext_ops.info;
1474 tplg_log(tplg, 'D', pos, "control bytes: name '%s' access 0x%x",
1475 bt->hdr.name, bt->hdr.access);
1476
1477 bt->priv = &bc->priv;
1478 return 0;
1479 }
1480
tplg_decode_control_bytes(snd_tplg_t *tplg, size_t pos, struct snd_soc_tplg_hdr *hdr, void *bin, size_t size)1481 int tplg_decode_control_bytes(snd_tplg_t *tplg,
1482 size_t pos,
1483 struct snd_soc_tplg_hdr *hdr,
1484 void *bin, size_t size)
1485 {
1486 snd_tplg_obj_template_t t;
1487 struct snd_tplg_bytes_template bt;
1488 struct snd_soc_tplg_bytes_control *bc;
1489 size_t size2;
1490 int err;
1491
1492 err = tplg_decode_template(tplg, pos, hdr, &t);
1493 if (err < 0)
1494 return err;
1495
1496 next:
1497 if (size < sizeof(*bc)) {
1498 SNDERR("bytes: small size %d", size);
1499 return -EINVAL;
1500 }
1501 bc = bin;
1502 size2 = bc->size + bc->priv.size;
1503 if (size2 > size) {
1504 SNDERR("bytes: wrong element size (%d, priv %d)",
1505 bc->size, bc->priv.size);
1506 return -EINVAL;
1507 }
1508
1509 err = tplg_decode_control_bytes1(tplg, &bt, pos, bin, size);
1510 if (err < 0)
1511 return err;
1512
1513 t.bytes_ctl = &bt;
1514 err = snd_tplg_add_object(tplg, &t);
1515 if (err < 0)
1516 return err;
1517
1518 bin += size2;
1519 size -= size2;
1520 pos += size2;
1521
1522 if (size > 0)
1523 goto next;
1524
1525 return 0;
1526 }
1527