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