2 Copyright(c) 2014-2015 Intel Corporation
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of version 2 of the GNU General Public License as
7 published by the Free Software Foundation.
9 This program is distributed in the hope that it will be useful, but
10 WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 General Public License for more details.
14 Authors: Mengdong Lin <mengdong.lin@intel.com>
15 Yao Jin <yao.jin@intel.com>
16 Liam Girdwood <liam.r.girdwood@linux.intel.com>
20 #include "tplg_local.h"
22 #define ENUM_VAL_SIZE (SNDRV_CTL_ELEM_ID_NAME_MAXLEN >> 2)
24 /* copy referenced TLV to the mixer control */
25 static int copy_tlv(struct tplg_elem *elem, struct tplg_elem *ref)
27 struct snd_soc_tplg_mixer_control *mixer_ctrl = elem->mixer_ctrl;
28 struct snd_soc_tplg_ctl_tlv *tlv = ref->tlv;
30 tplg_dbg("TLV '%s' used by '%s\n", ref->id, elem->id);
32 /* TLV has a fixed size */
33 mixer_ctrl->hdr.tlv = *tlv;
37 /* check referenced TLV for a mixer control */
38 static int tplg_build_mixer_control(snd_tplg_t *tplg,
39 struct tplg_elem *elem)
42 struct list_head *base, *pos;
45 base = &elem->ref_list;
47 /* for each ref in this control elem */
48 list_for_each(pos, base) {
50 ref = list_entry(pos, struct tplg_ref, list);
51 if (ref->id == NULL || ref->elem)
54 if (ref->type == SND_TPLG_TYPE_TLV) {
55 ref->elem = tplg_elem_lookup(&tplg->tlv_list,
56 ref->id, SND_TPLG_TYPE_TLV);
58 err = copy_tlv(elem, ref->elem);
60 } else if (ref->type == SND_TPLG_TYPE_DATA) {
61 ref->elem = tplg_elem_lookup(&tplg->pdata_list,
62 ref->id, SND_TPLG_TYPE_DATA);
63 err = tplg_copy_data(elem, ref->elem);
67 SNDERR("error: cannot find '%s' referenced by"
68 " control '%s'\n", ref->id, elem->id);
77 static void copy_enum_texts(struct tplg_elem *enum_elem,
78 struct tplg_elem *ref_elem)
80 struct snd_soc_tplg_enum_control *ec = enum_elem->enum_ctrl;
82 memcpy(ec->texts, ref_elem->texts,
83 SND_SOC_TPLG_NUM_TEXTS * SNDRV_CTL_ELEM_ID_NAME_MAXLEN);
86 /* check referenced text for a enum control */
87 static int tplg_build_enum_control(snd_tplg_t *tplg,
88 struct tplg_elem *elem)
91 struct list_head *base, *pos;
94 base = &elem->ref_list;
96 list_for_each(pos, base) {
98 ref = list_entry(pos, struct tplg_ref, list);
99 if (ref->id == NULL || ref->elem)
102 if (ref->type == SND_TPLG_TYPE_TEXT) {
103 ref->elem = tplg_elem_lookup(&tplg->text_list,
104 ref->id, SND_TPLG_TYPE_TEXT);
106 copy_enum_texts(elem, ref->elem);
108 } else if (ref->type == SND_TPLG_TYPE_DATA) {
109 ref->elem = tplg_elem_lookup(&tplg->pdata_list,
110 ref->id, SND_TPLG_TYPE_DATA);
111 err = tplg_copy_data(elem, ref->elem);
114 SNDERR("error: cannot find '%s' referenced by"
115 " control '%s'\n", ref->id, elem->id);
124 /* check referenced private data for a byte control */
125 static int tplg_build_bytes_control(snd_tplg_t *tplg, struct tplg_elem *elem)
127 struct tplg_ref *ref;
128 struct list_head *base, *pos;
130 base = &elem->ref_list;
132 list_for_each(pos, base) {
134 ref = list_entry(pos, struct tplg_ref, list);
135 if (ref->id == NULL || ref->elem)
138 /* bytes control only reference one private data section */
139 ref->elem = tplg_elem_lookup(&tplg->pdata_list,
140 ref->id, SND_TPLG_TYPE_DATA);
142 SNDERR("error: cannot find data '%s'"
143 " referenced by control '%s'\n",
148 /* copy texts to enum elem */
149 return tplg_copy_data(elem, ref->elem);
155 int tplg_build_controls(snd_tplg_t *tplg)
157 struct list_head *base, *pos;
158 struct tplg_elem *elem;
161 base = &tplg->mixer_list;
162 list_for_each(pos, base) {
164 elem = list_entry(pos, struct tplg_elem, list);
165 err = tplg_build_mixer_control(tplg, elem);
169 /* add control to manifest */
170 tplg->manifest.control_elems++;
173 base = &tplg->enum_list;
174 list_for_each(pos, base) {
176 elem = list_entry(pos, struct tplg_elem, list);
177 err = tplg_build_enum_control(tplg, elem);
181 /* add control to manifest */
182 tplg->manifest.control_elems++;
185 base = &tplg->bytes_ext_list;
186 list_for_each(pos, base) {
188 elem = list_entry(pos, struct tplg_elem, list);
189 err = tplg_build_bytes_control(tplg, elem);
193 /* add control to manifest */
194 tplg->manifest.control_elems++;
202 * Parse TLV of DBScale type.
204 * Parse DBScale describing min, step, mute in DB.
206 static int tplg_parse_tlv_dbscale(snd_config_t *cfg, struct tplg_elem *elem)
208 snd_config_iterator_t i, next;
210 struct snd_soc_tplg_ctl_tlv *tplg_tlv;
211 struct snd_soc_tplg_tlv_dbscale *scale;
212 const char *id = NULL, *value = NULL;
214 tplg_dbg(" scale: %s\n", elem->id);
216 tplg_tlv = calloc(1, sizeof(*tplg_tlv));
220 elem->tlv = tplg_tlv;
221 tplg_tlv->size = sizeof(struct snd_soc_tplg_ctl_tlv);
222 tplg_tlv->type = SNDRV_CTL_TLVT_DB_SCALE;
223 scale = &tplg_tlv->scale;
225 snd_config_for_each(i, next, cfg) {
227 n = snd_config_iterator_entry(i);
230 if (snd_config_get_id(n, &id) < 0) {
231 SNDERR("error: cant get ID\n");
236 if (snd_config_get_string(n, &value) < 0)
239 tplg_dbg("\t%s = %s\n", id, value);
242 if (strcmp(id, "min") == 0)
243 scale->min = atoi(value);
244 else if (strcmp(id, "step") == 0)
245 scale->step = atoi(value);
246 else if (strcmp(id, "mute") == 0)
247 scale->mute = atoi(value);
249 SNDERR("error: unknown key %s\n", id);
256 int tplg_parse_tlv(snd_tplg_t *tplg, snd_config_t *cfg,
257 void *private ATTRIBUTE_UNUSED)
259 snd_config_iterator_t i, next;
263 struct tplg_elem *elem;
265 elem = tplg_elem_new_common(tplg, cfg, NULL, SND_TPLG_TYPE_TLV);
269 snd_config_for_each(i, next, cfg) {
271 n = snd_config_iterator_entry(i);
272 if (snd_config_get_id(n, &id) < 0)
275 if (strcmp(id, "scale") == 0) {
276 err = tplg_parse_tlv_dbscale(n, elem);
278 SNDERR("error: failed to DBScale");
288 /* Parse Control Bytes */
289 int tplg_parse_control_bytes(snd_tplg_t *tplg,
290 snd_config_t *cfg, void *private ATTRIBUTE_UNUSED)
292 struct snd_soc_tplg_bytes_control *be;
293 struct tplg_elem *elem;
294 snd_config_iterator_t i, next;
296 const char *id, *val = NULL;
299 elem = tplg_elem_new_common(tplg, cfg, NULL, SND_TPLG_TYPE_BYTES);
303 be = elem->bytes_ext;
304 be->size = elem->size;
305 elem_copy_text(be->hdr.name, elem->id, SNDRV_CTL_ELEM_ID_NAME_MAXLEN);
306 be->hdr.type = SND_SOC_TPLG_TYPE_BYTES;
308 tplg_dbg(" Control Bytes: %s\n", elem->id);
310 snd_config_for_each(i, next, cfg) {
311 n = snd_config_iterator_entry(i);
312 if (snd_config_get_id(n, &id) < 0)
316 if (strcmp(id, "comment") == 0)
321 if (strcmp(id, "index") == 0) {
322 if (snd_config_get_string(n, &val) < 0)
325 elem->index = atoi(val);
326 tplg_dbg("\t%s: %d\n", id, elem->index);
330 if (strcmp(id, "base") == 0) {
331 if (snd_config_get_string(n, &val) < 0)
334 be->base = atoi(val);
335 tplg_dbg("\t%s: %d\n", id, be->base);
339 if (strcmp(id, "num_regs") == 0) {
340 if (snd_config_get_string(n, &val) < 0)
343 be->num_regs = atoi(val);
344 tplg_dbg("\t%s: %d\n", id, be->num_regs);
348 if (strcmp(id, "max") == 0) {
349 if (snd_config_get_string(n, &val) < 0)
353 tplg_dbg("\t%s: %d\n", id, be->max);
357 if (strcmp(id, "mask") == 0) {
358 if (snd_config_get_string(n, &val) < 0)
361 be->mask = strtol(val, NULL, 16);
362 tplg_dbg("\t%s: %d\n", id, be->mask);
366 if (strcmp(id, "data") == 0) {
367 if (snd_config_get_string(n, &val) < 0)
370 tplg_ref_add(elem, SND_TPLG_TYPE_DATA, val);
371 tplg_dbg("\t%s: %s\n", id, val);
375 if (strcmp(id, "tlv") == 0) {
376 if (snd_config_get_string(n, &val) < 0)
379 err = tplg_ref_add(elem, SND_TPLG_TYPE_TLV, val);
383 be->hdr.access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |
384 SNDRV_CTL_ELEM_ACCESS_READWRITE;
385 tplg_dbg("\t%s: %s\n", id, val);
389 if (strcmp(id, "ops") == 0) {
390 err = tplg_parse_compound(tplg, n, tplg_parse_ops,
397 if (strcmp(id, "extops") == 0) {
398 err = tplg_parse_compound(tplg, n, tplg_parse_ext_ops,
409 /* Parse Control Enums. */
410 int tplg_parse_control_enum(snd_tplg_t *tplg, snd_config_t *cfg,
411 void *private ATTRIBUTE_UNUSED)
413 struct snd_soc_tplg_enum_control *ec;
414 struct tplg_elem *elem;
415 snd_config_iterator_t i, next;
417 const char *id, *val = NULL;
420 elem = tplg_elem_new_common(tplg, cfg, NULL, SND_TPLG_TYPE_ENUM);
424 ec = elem->enum_ctrl;
425 elem_copy_text(ec->hdr.name, elem->id, SNDRV_CTL_ELEM_ID_NAME_MAXLEN);
426 ec->hdr.type = SND_SOC_TPLG_TYPE_ENUM;
427 ec->size = elem->size;
428 tplg->channel_idx = 0;
430 /* set channel reg to default state */
431 for (j = 0; j < SND_SOC_TPLG_MAX_CHAN; j++)
432 ec->channel[j].reg = -1;
434 tplg_dbg(" Control Enum: %s\n", elem->id);
436 snd_config_for_each(i, next, cfg) {
438 n = snd_config_iterator_entry(i);
439 if (snd_config_get_id(n, &id) < 0)
443 if (strcmp(id, "comment") == 0)
448 if (strcmp(id, "index") == 0) {
449 if (snd_config_get_string(n, &val) < 0)
452 elem->index = atoi(val);
453 tplg_dbg("\t%s: %d\n", id, elem->index);
457 if (strcmp(id, "texts") == 0) {
458 if (snd_config_get_string(n, &val) < 0)
461 tplg_ref_add(elem, SND_TPLG_TYPE_TEXT, val);
462 tplg_dbg("\t%s: %s\n", id, val);
466 if (strcmp(id, "channel") == 0) {
467 if (ec->num_channels >= SND_SOC_TPLG_MAX_CHAN) {
468 SNDERR("error: too many channels %s\n",
473 err = tplg_parse_compound(tplg, n, tplg_parse_channel,
478 ec->num_channels = tplg->channel_idx;
482 if (strcmp(id, "ops") == 0) {
483 err = tplg_parse_compound(tplg, n, tplg_parse_ops,
490 if (strcmp(id, "data") == 0) {
491 if (snd_config_get_string(n, &val) < 0)
494 tplg_ref_add(elem, SND_TPLG_TYPE_DATA, val);
495 tplg_dbg("\t%s: %s\n", id, val);
505 * Mixer control. Supports multiple channels.
507 int tplg_parse_control_mixer(snd_tplg_t *tplg,
508 snd_config_t *cfg, void *private ATTRIBUTE_UNUSED)
510 struct snd_soc_tplg_mixer_control *mc;
511 struct tplg_elem *elem;
512 snd_config_iterator_t i, next;
514 const char *id, *val = NULL;
517 elem = tplg_elem_new_common(tplg, cfg, NULL, SND_TPLG_TYPE_MIXER);
522 mc = elem->mixer_ctrl;
523 elem_copy_text(mc->hdr.name, elem->id, SNDRV_CTL_ELEM_ID_NAME_MAXLEN);
524 mc->hdr.type = SND_SOC_TPLG_TYPE_MIXER;
525 mc->size = elem->size;
526 tplg->channel_idx = 0;
528 /* set channel reg to default state */
529 for (j = 0; j < SND_SOC_TPLG_MAX_CHAN; j++)
530 mc->channel[j].reg = -1;
532 tplg_dbg(" Control Mixer: %s\n", elem->id);
534 /* giterate trough each mixer elment */
535 snd_config_for_each(i, next, cfg) {
536 n = snd_config_iterator_entry(i);
537 if (snd_config_get_id(n, &id) < 0)
541 if (strcmp(id, "comment") == 0)
546 if (strcmp(id, "index") == 0) {
547 if (snd_config_get_string(n, &val) < 0)
550 elem->index = atoi(val);
551 tplg_dbg("\t%s: %d\n", id, elem->index);
555 if (strcmp(id, "channel") == 0) {
556 if (mc->num_channels >= SND_SOC_TPLG_MAX_CHAN) {
557 SNDERR("error: too many channels %s\n",
562 err = tplg_parse_compound(tplg, n, tplg_parse_channel,
567 mc->num_channels = tplg->channel_idx;
571 if (strcmp(id, "max") == 0) {
572 if (snd_config_get_string(n, &val) < 0)
576 tplg_dbg("\t%s: %d\n", id, mc->max);
580 if (strcmp(id, "invert") == 0) {
581 if (snd_config_get_string(n, &val) < 0)
584 if (strcmp(val, "true") == 0)
586 else if (strcmp(val, "false") == 0)
589 tplg_dbg("\t%s: %d\n", id, mc->invert);
593 if (strcmp(id, "ops") == 0) {
594 err = tplg_parse_compound(tplg, n, tplg_parse_ops,
601 if (strcmp(id, "tlv") == 0) {
602 if (snd_config_get_string(n, &val) < 0)
605 err = tplg_ref_add(elem, SND_TPLG_TYPE_TLV, val);
609 mc->hdr.access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |
610 SNDRV_CTL_ELEM_ACCESS_READWRITE;
611 tplg_dbg("\t%s: %s\n", id, val);
615 if (strcmp(id, "data") == 0) {
616 if (snd_config_get_string(n, &val) < 0)
619 tplg_ref_add(elem, SND_TPLG_TYPE_DATA, val);
620 tplg_dbg("\t%s: %s\n", id, val);
628 static int init_ctl_hdr(struct snd_soc_tplg_ctl_hdr *hdr,
629 struct snd_tplg_ctl_template *t)
631 hdr->size = sizeof(struct snd_soc_tplg_ctl_hdr);
634 elem_copy_text(hdr->name, t->name,
635 SNDRV_CTL_ELEM_ID_NAME_MAXLEN);
637 /* clean up access flag */
639 t->access = SNDRV_CTL_ELEM_ACCESS_READWRITE;
640 t->access &= (SNDRV_CTL_ELEM_ACCESS_READWRITE |
641 SNDRV_CTL_ELEM_ACCESS_VOLATILE |
642 SNDRV_CTL_ELEM_ACCESS_INACTIVE |
643 SNDRV_CTL_ELEM_ACCESS_TLV_READWRITE |
644 SNDRV_CTL_ELEM_ACCESS_TLV_COMMAND |
645 SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK);
647 hdr->access = t->access;
648 hdr->ops.get = t->ops.get;
649 hdr->ops.put = t->ops.put;
650 hdr->ops.info = t->ops.info;
653 if (hdr->access & SNDRV_CTL_ELEM_ACCESS_TLV_READWRITE
654 && !(hdr->access & SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK)) {
656 struct snd_tplg_tlv_template *tlvt = t->tlv;
657 struct snd_soc_tplg_ctl_tlv *tlv = &hdr->tlv;
658 struct snd_tplg_tlv_dbscale_template *scalet;
659 struct snd_soc_tplg_tlv_dbscale *scale;
662 SNDERR("error: missing TLV data\n");
666 tlv->size = sizeof(struct snd_soc_tplg_ctl_tlv);
667 tlv->type = tlvt->type;
669 switch (tlvt->type) {
670 case SNDRV_CTL_TLVT_DB_SCALE:
671 scalet = container_of(tlvt,
672 struct snd_tplg_tlv_dbscale_template, hdr);
674 scale->min = scalet->min;
675 scale->step = scalet->step;
676 scale->mute = scalet->mute;
679 /* TODO: add support for other TLV types */
681 SNDERR("error: unsupported TLV type %d\n", tlv->type);
689 int tplg_add_mixer(snd_tplg_t *tplg, struct snd_tplg_mixer_template *mixer,
690 struct tplg_elem **e)
692 struct snd_soc_tplg_private *priv = mixer->priv;
693 struct snd_soc_tplg_mixer_control *mc;
694 struct tplg_elem *elem;
695 int ret, i, num_channels;
697 tplg_dbg(" Control Mixer: %s\n", mixer->hdr.name);
699 if (mixer->hdr.type != SND_SOC_TPLG_TYPE_MIXER) {
700 SNDERR("error: invalid mixer type %d\n", mixer->hdr.type);
704 elem = tplg_elem_new_common(tplg, NULL, mixer->hdr.name,
705 SND_TPLG_TYPE_MIXER);
710 mc = elem->mixer_ctrl;
711 mc->size = elem->size;
712 ret = init_ctl_hdr(&mc->hdr, &mixer->hdr);
714 tplg_elem_free(elem);
718 mc->min = mixer->min;
719 mc->max = mixer->max;
720 mc->platform_max = mixer->platform_max;
721 mc->invert = mixer->invert;
723 /* set channel reg to default state */
724 for (i = 0; i < SND_SOC_TPLG_MAX_CHAN; i++)
725 mc->channel[i].reg = -1;
727 num_channels = mixer->map ? mixer->map->num_channels : 0;
728 mc->num_channels = num_channels;
730 for (i = 0; i < num_channels; i++) {
731 struct snd_tplg_channel_elem *channel = &mixer->map->channel[i];
733 mc->channel[i].size = channel->size;
734 mc->channel[i].reg = channel->reg;
735 mc->channel[i].shift = channel->shift;
736 mc->channel[i].id = channel->id;
741 mc = realloc(mc, elem->size + priv->size);
743 tplg_elem_free(elem);
747 elem->mixer_ctrl = mc;
748 elem->size += priv->size;
749 mc->priv.size = priv->size;
750 memcpy(mc->priv.data, priv->data, priv->size);
758 int tplg_add_enum(snd_tplg_t *tplg, struct snd_tplg_enum_template *enum_ctl,
759 struct tplg_elem **e)
761 struct snd_soc_tplg_enum_control *ec;
762 struct tplg_elem *elem;
763 int ret, i, num_items;
765 tplg_dbg(" Control Enum: %s\n", enum_ctl->hdr.name);
767 if (enum_ctl->hdr.type != SND_SOC_TPLG_TYPE_ENUM) {
768 SNDERR("error: invalid enum type %d\n", enum_ctl->hdr.type);
772 elem = tplg_elem_new_common(tplg, NULL, enum_ctl->hdr.name,
777 ec = elem->enum_ctrl;
778 ec->size = elem->size;
779 ret = init_ctl_hdr(&ec->hdr, &enum_ctl->hdr);
781 tplg_elem_free(elem);
785 num_items = enum_ctl->items < SND_SOC_TPLG_NUM_TEXTS ?
786 enum_ctl->items : SND_SOC_TPLG_NUM_TEXTS;
787 ec->items = num_items;
788 ec->mask = enum_ctl->mask;
789 ec->count = enum_ctl->items;
791 if (enum_ctl->texts != NULL) {
792 for (i = 0; i < num_items; i++) {
793 if (enum_ctl->texts[i] != NULL)
794 strncpy(ec->texts[i], enum_ctl->texts[i],
795 SNDRV_CTL_ELEM_ID_NAME_MAXLEN);
799 if (enum_ctl->values != NULL) {
800 for (i = 0; i < num_items; i++) {
801 if (enum_ctl->values[i])
804 memcpy(&ec->values[i * sizeof(int) * ENUM_VAL_SIZE],
806 sizeof(int) * ENUM_VAL_SIZE);
810 if (enum_ctl->priv != NULL) {
812 elem->size + enum_ctl->priv->size);
814 tplg_elem_free(elem);
818 elem->enum_ctrl = ec;
819 elem->size += enum_ctl->priv->size;
821 memcpy(ec->priv.data, enum_ctl->priv->data,
822 enum_ctl->priv->size);
824 ec->priv.size = enum_ctl->priv->size;
832 int tplg_add_bytes(snd_tplg_t *tplg, struct snd_tplg_bytes_template *bytes_ctl,
833 struct tplg_elem **e)
835 struct snd_soc_tplg_bytes_control *be;
836 struct tplg_elem *elem;
839 tplg_dbg(" Control Bytes: %s\n", bytes_ctl->hdr.name);
841 if (bytes_ctl->hdr.type != SND_SOC_TPLG_TYPE_BYTES) {
842 SNDERR("error: invalid bytes type %d\n", bytes_ctl->hdr.type);
846 elem = tplg_elem_new_common(tplg, NULL, bytes_ctl->hdr.name,
847 SND_TPLG_TYPE_BYTES);
851 be = elem->bytes_ext;
852 be->size = elem->size;
853 ret = init_ctl_hdr(&be->hdr, &bytes_ctl->hdr);
855 tplg_elem_free(elem);
859 be->max = bytes_ctl->max;
860 be->mask = bytes_ctl->mask;
861 be->base = bytes_ctl->base;
862 be->num_regs = bytes_ctl->num_regs;
863 be->ext_ops.put = bytes_ctl->ext_ops.put;
864 be->ext_ops.get = bytes_ctl->ext_ops.get;
866 if (bytes_ctl->priv != NULL) {
868 elem->size + bytes_ctl->priv->size);
870 tplg_elem_free(elem);
873 elem->bytes_ext = be;
874 elem->size += bytes_ctl->priv->size;
876 memcpy(be->priv.data, bytes_ctl->priv->data,
877 bytes_ctl->priv->size);
879 be->priv.size = bytes_ctl->priv->size;
882 /* check on TLV bytes control */
883 if (be->hdr.access & SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK) {
884 if ((be->hdr.access & SNDRV_CTL_ELEM_ACCESS_TLV_READWRITE)
885 != SNDRV_CTL_ELEM_ACCESS_TLV_READWRITE) {
886 SNDERR("error: Invalid TLV bytes control access 0x%x\n",
888 tplg_elem_free(elem);
893 tplg_elem_free(elem);
903 int tplg_add_mixer_object(snd_tplg_t *tplg, snd_tplg_obj_template_t *t)
905 return tplg_add_mixer(tplg, t->mixer, NULL);
908 int tplg_add_enum_object(snd_tplg_t *tplg, snd_tplg_obj_template_t *t)
910 return tplg_add_enum(tplg, t->enum_ctl, NULL);
913 int tplg_add_bytes_object(snd_tplg_t *tplg, snd_tplg_obj_template_t *t)
915 return tplg_add_bytes(tplg, t->bytes_ctl, NULL);