Lines Matching +full:stream +full:- +full:match +full:- +full:mask
1 // SPDX-License-Identifier: GPL-2.0+
3 // soc-topology.c -- ALSA SoC Topology
29 #include <sound/soc-dapm.h>
30 #include <sound/soc-topology.h>
90 const u8 *end = tplg->pos + elem_size * count; in soc_tplg_check_elem_count()
92 if (end > tplg->fw->data + tplg->fw->size) { in soc_tplg_check_elem_count()
93 dev_err(tplg->dev, "ASoC: %s overflow end of data\n", in soc_tplg_check_elem_count()
95 return -EINVAL; in soc_tplg_check_elem_count()
101 dev_err(tplg->dev, in soc_tplg_check_elem_count()
104 return -EINVAL; in soc_tplg_check_elem_count()
112 const u8 *end = tplg->hdr_pos; in soc_tplg_is_eof()
114 if (end >= tplg->fw->data + tplg->fw->size) in soc_tplg_is_eof()
121 return (unsigned long)(tplg->hdr_pos - tplg->fw->data); in soc_tplg_get_hdr_offset()
126 return (unsigned long)(tplg->pos - tplg->fw->data); in soc_tplg_get_offset()
202 return -EINVAL; in tplc_chan_get_reg()
215 return -EINVAL; in tplc_chan_get_shift()
227 return -EINVAL; in get_widget_id()
233 dev_err(tplg->dev, in soc_bind_err()
235 hdr->ops.get, hdr->ops.put, hdr->ops.info, index, in soc_bind_err()
242 dev_err(tplg->dev, in soc_control_err()
244 name, hdr->ops.get, hdr->ops.put, hdr->ops.info, in soc_control_err()
254 if (tplg->ops && tplg->ops->vendor_load) in soc_tplg_vendor_load()
255 ret = tplg->ops->vendor_load(tplg->comp, tplg->index, hdr); in soc_tplg_vendor_load()
257 dev_err(tplg->dev, "ASoC: no vendor load callback for ID %d\n", in soc_tplg_vendor_load()
258 hdr->vendor_type); in soc_tplg_vendor_load()
259 return -EINVAL; in soc_tplg_vendor_load()
263 dev_err(tplg->dev, in soc_tplg_vendor_load()
267 hdr->type, hdr->vendor_type); in soc_tplg_vendor_load()
276 if (tplg->ops && tplg->ops->widget_load) in soc_tplg_widget_load()
277 return tplg->ops->widget_load(tplg->comp, tplg->index, w, in soc_tplg_widget_load()
288 if (tplg->ops && tplg->ops->widget_ready) in soc_tplg_widget_ready()
289 return tplg->ops->widget_ready(tplg->comp, tplg->index, w, in soc_tplg_widget_ready()
300 if (tplg->ops && tplg->ops->dai_load) in soc_tplg_dai_load()
301 return tplg->ops->dai_load(tplg->comp, tplg->index, dai_drv, in soc_tplg_dai_load()
311 if (tplg->ops && tplg->ops->link_load) in soc_tplg_dai_link_load()
312 return tplg->ops->link_load(tplg->comp, tplg->index, link, cfg); in soc_tplg_dai_link_load()
320 if (tplg->ops && tplg->ops->complete) in soc_tplg_complete()
321 tplg->ops->complete(tplg->comp); in soc_tplg_complete()
331 *kcontrol = snd_soc_cnew(control_new, data, control_new->name, prefix); in soc_tplg_add_dcontrol()
334 control_new->name); in soc_tplg_add_dcontrol()
335 return -ENOMEM; in soc_tplg_add_dcontrol()
341 control_new->name, err); in soc_tplg_add_dcontrol()
352 struct snd_soc_component *comp = tplg->comp; in soc_tplg_add_kcontrol()
354 return soc_tplg_add_dcontrol(comp->card->snd_card, in soc_tplg_add_kcontrol()
355 comp->dev, k, comp->name_prefix, comp, kcontrol); in soc_tplg_add_kcontrol()
362 struct snd_card *card = comp->card->snd_card; in remove_mixer()
370 if (dobj->ops && dobj->ops->control_unload) in remove_mixer()
371 dobj->ops->control_unload(comp, dobj); in remove_mixer()
373 if (dobj->control.kcontrol->tlv.p) in remove_mixer()
374 p = dobj->control.kcontrol->tlv.p; in remove_mixer()
375 snd_ctl_remove(card, dobj->control.kcontrol); in remove_mixer()
376 list_del(&dobj->list); in remove_mixer()
385 struct snd_card *card = comp->card->snd_card; in remove_enum()
391 if (dobj->ops && dobj->ops->control_unload) in remove_enum()
392 dobj->ops->control_unload(comp, dobj); in remove_enum()
394 snd_ctl_remove(card, dobj->control.kcontrol); in remove_enum()
395 list_del(&dobj->list); in remove_enum()
406 struct snd_card *card = comp->card->snd_card; in remove_bytes()
413 if (dobj->ops && dobj->ops->control_unload) in remove_bytes()
414 dobj->ops->control_unload(comp, dobj); in remove_bytes()
416 snd_ctl_remove(card, dobj->control.kcontrol); in remove_bytes()
417 list_del(&dobj->list); in remove_bytes()
431 if (dobj->ops && dobj->ops->dapm_route_unload) in remove_route()
432 dobj->ops->dapm_route_unload(comp, dobj); in remove_route()
434 list_del(&dobj->list); in remove_route()
438 /* remove a widget and it's kcontrols - routes must be removed first */
442 struct snd_card *card = comp->card->snd_card; in remove_widget()
450 if (dobj->ops && dobj->ops->widget_unload) in remove_widget()
451 dobj->ops->widget_unload(comp, dobj); in remove_widget()
453 if (!w->kcontrols) in remove_widget()
460 if (dobj->widget.kcontrol_type == SND_SOC_TPLG_TYPE_ENUM) { in remove_widget()
462 for (i = 0; w->kcontrols != NULL && i < w->num_kcontrols; i++) { in remove_widget()
463 struct snd_kcontrol *kcontrol = w->kcontrols[i]; in remove_widget()
465 (struct soc_enum *)kcontrol->private_value; in remove_widget()
474 kfree(w->kcontrol_news[i].name); in remove_widget()
478 for (i = 0; w->kcontrols != NULL && i < w->num_kcontrols; i++) { in remove_widget()
479 struct snd_kcontrol *kcontrol = w->kcontrols[i]; in remove_widget()
481 if (dobj->widget.kcontrol_type in remove_widget()
483 kfree(kcontrol->tlv.p); in remove_widget()
489 kfree((void *)kcontrol->private_value); in remove_widget()
491 kfree(w->kcontrol_news[i].name); in remove_widget()
496 kfree(w->kcontrol_news); in remove_widget()
498 list_del(&dobj->list); in remove_widget()
500 /* widget w is freed by soc-dapm.c */ in remove_widget()
514 if (dobj->ops && dobj->ops->dai_unload) in remove_dai()
515 dobj->ops->dai_unload(comp, dobj); in remove_dai()
518 if (dai->driver == dai_drv) in remove_dai()
519 dai->driver = NULL; in remove_dai()
521 kfree(dai_drv->playback.stream_name); in remove_dai()
522 kfree(dai_drv->capture.stream_name); in remove_dai()
523 kfree(dai_drv->name); in remove_dai()
524 list_del(&dobj->list); in remove_dai()
538 if (dobj->ops && dobj->ops->link_unload) in remove_link()
539 dobj->ops->link_unload(comp, dobj); in remove_link()
541 list_del(&dobj->list); in remove_link()
542 snd_soc_remove_pcm_runtime(comp->card, in remove_link()
543 snd_soc_get_pcm_runtime(comp->card, link)); in remove_link()
545 kfree(link->name); in remove_link()
546 kfree(link->stream_name); in remove_link()
547 kfree(link->cpus->dai_name); in remove_link()
558 if (dobj->ops && dobj->ops->link_unload) in remove_backend_link()
559 dobj->ops->link_unload(comp, dobj); in remove_backend_link()
566 dobj->type = SND_SOC_DOBJ_NONE; in remove_backend_link()
567 list_del(&dobj->list); in remove_backend_link()
579 if (le32_to_cpu(hdr->ops.info) == SND_SOC_TPLG_CTL_BYTES in soc_tplg_kcontrol_bind_io()
580 && k->iface & SNDRV_CTL_ELEM_IFACE_MIXER in soc_tplg_kcontrol_bind_io()
581 && k->access & SNDRV_CTL_ELEM_ACCESS_TLV_READWRITE in soc_tplg_kcontrol_bind_io()
582 && k->access & SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK) { in soc_tplg_kcontrol_bind_io()
586 sbe = (struct soc_bytes_ext *)k->private_value; in soc_tplg_kcontrol_bind_io()
592 k->info = snd_soc_bytes_info_ext; in soc_tplg_kcontrol_bind_io()
593 k->tlv.c = snd_soc_bytes_tlv_callback; in soc_tplg_kcontrol_bind_io()
596 * When a topology-based implementation abuses the in soc_tplg_kcontrol_bind_io()
600 * return an -EINVAL error and prevent the card from in soc_tplg_kcontrol_bind_io()
603 if (IS_ENABLED(CONFIG_SND_CTL_VALIDATION) && sbe->max > 512) in soc_tplg_kcontrol_bind_io()
604 k->access |= SNDRV_CTL_ELEM_ACCESS_SKIP_CHECK; in soc_tplg_kcontrol_bind_io()
606 ext_ops = tplg->bytes_ext_ops; in soc_tplg_kcontrol_bind_io()
607 num_ops = tplg->bytes_ext_ops_count; in soc_tplg_kcontrol_bind_io()
609 if (!sbe->put && in soc_tplg_kcontrol_bind_io()
610 ext_ops[i].id == le32_to_cpu(be->ext_ops.put)) in soc_tplg_kcontrol_bind_io()
611 sbe->put = ext_ops[i].put; in soc_tplg_kcontrol_bind_io()
612 if (!sbe->get && in soc_tplg_kcontrol_bind_io()
613 ext_ops[i].id == le32_to_cpu(be->ext_ops.get)) in soc_tplg_kcontrol_bind_io()
614 sbe->get = ext_ops[i].get; in soc_tplg_kcontrol_bind_io()
617 if ((k->access & SNDRV_CTL_ELEM_ACCESS_TLV_READ) && !sbe->get) in soc_tplg_kcontrol_bind_io()
618 return -EINVAL; in soc_tplg_kcontrol_bind_io()
619 if ((k->access & SNDRV_CTL_ELEM_ACCESS_TLV_WRITE) && !sbe->put) in soc_tplg_kcontrol_bind_io()
620 return -EINVAL; in soc_tplg_kcontrol_bind_io()
625 ops = tplg->io_ops; in soc_tplg_kcontrol_bind_io()
626 num_ops = tplg->io_ops_count; in soc_tplg_kcontrol_bind_io()
629 if (k->put == NULL && ops[i].id == le32_to_cpu(hdr->ops.put)) in soc_tplg_kcontrol_bind_io()
630 k->put = ops[i].put; in soc_tplg_kcontrol_bind_io()
631 if (k->get == NULL && ops[i].id == le32_to_cpu(hdr->ops.get)) in soc_tplg_kcontrol_bind_io()
632 k->get = ops[i].get; in soc_tplg_kcontrol_bind_io()
633 if (k->info == NULL && ops[i].id == le32_to_cpu(hdr->ops.info)) in soc_tplg_kcontrol_bind_io()
634 k->info = ops[i].info; in soc_tplg_kcontrol_bind_io()
638 if (k->put && k->get && k->info) in soc_tplg_kcontrol_bind_io()
646 if (k->put == NULL && ops[i].id == le32_to_cpu(hdr->ops.put)) in soc_tplg_kcontrol_bind_io()
647 k->put = ops[i].put; in soc_tplg_kcontrol_bind_io()
648 if (k->get == NULL && ops[i].id == le32_to_cpu(hdr->ops.get)) in soc_tplg_kcontrol_bind_io()
649 k->get = ops[i].get; in soc_tplg_kcontrol_bind_io()
650 if (k->info == NULL && ops[i].id == le32_to_cpu(hdr->ops.info)) in soc_tplg_kcontrol_bind_io()
651 k->info = ops[i].info; in soc_tplg_kcontrol_bind_io()
655 if (k->put && k->get && k->info) in soc_tplg_kcontrol_bind_io()
659 return -EINVAL; in soc_tplg_kcontrol_bind_io()
669 w->event = NULL; in snd_soc_tplg_widget_bind_event()
674 /* found - so assign event */ in snd_soc_tplg_widget_bind_event()
675 w->event = events[i].event_handler; in snd_soc_tplg_widget_bind_event()
681 return -EINVAL; in snd_soc_tplg_widget_bind_event()
689 if (tplg->ops && tplg->ops->control_load) in soc_tplg_init_kcontrol()
690 return tplg->ops->control_load(tplg->comp, tplg->index, k, in soc_tplg_init_kcontrol()
705 return -ENOMEM; in soc_tplg_create_tlv_db_scale()
709 p[2] = le32_to_cpu(scale->min); in soc_tplg_create_tlv_db_scale()
710 p[3] = (le32_to_cpu(scale->step) & TLV_DB_SCALE_MASK) in soc_tplg_create_tlv_db_scale()
711 | (le32_to_cpu(scale->mute) ? TLV_DB_SCALE_MUTE : 0); in soc_tplg_create_tlv_db_scale()
713 kc->tlv.p = (void *)p; in soc_tplg_create_tlv_db_scale()
721 u32 access = le32_to_cpu(tc->access); in soc_tplg_create_tlv()
727 tplg_tlv = &tc->tlv; in soc_tplg_create_tlv()
728 switch (le32_to_cpu(tplg_tlv->type)) { in soc_tplg_create_tlv()
731 &tplg_tlv->scale); in soc_tplg_create_tlv()
735 dev_dbg(tplg->dev, "Unsupported TLV type %d\n", in soc_tplg_create_tlv()
736 tplg_tlv->type); in soc_tplg_create_tlv()
737 return -EINVAL; in soc_tplg_create_tlv()
747 kfree(kc->tlv.p); in soc_tplg_free_tlv()
762 dev_err(tplg->dev, "ASoC: Invalid count %d for byte control\n", in soc_tplg_dbytes_create()
764 return -EINVAL; in soc_tplg_dbytes_create()
768 be = (struct snd_soc_tplg_bytes_control *)tplg->pos; in soc_tplg_dbytes_create()
771 if (strnlen(be->hdr.name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN) == in soc_tplg_dbytes_create()
773 return -EINVAL; in soc_tplg_dbytes_create()
777 return -ENOMEM; in soc_tplg_dbytes_create()
779 tplg->pos += (sizeof(struct snd_soc_tplg_bytes_control) + in soc_tplg_dbytes_create()
780 le32_to_cpu(be->priv.size)); in soc_tplg_dbytes_create()
782 dev_dbg(tplg->dev, in soc_tplg_dbytes_create()
784 be->hdr.name, be->hdr.access); in soc_tplg_dbytes_create()
787 kc.name = be->hdr.name; in soc_tplg_dbytes_create()
790 kc.access = le32_to_cpu(be->hdr.access); in soc_tplg_dbytes_create()
792 sbe->max = le32_to_cpu(be->max); in soc_tplg_dbytes_create()
793 sbe->dobj.type = SND_SOC_DOBJ_BYTES; in soc_tplg_dbytes_create()
794 sbe->dobj.ops = tplg->ops; in soc_tplg_dbytes_create()
795 INIT_LIST_HEAD(&sbe->dobj.list); in soc_tplg_dbytes_create()
798 err = soc_tplg_kcontrol_bind_io(&be->hdr, &kc, tplg); in soc_tplg_dbytes_create()
800 soc_control_err(tplg, &be->hdr, be->hdr.name); in soc_tplg_dbytes_create()
809 dev_err(tplg->dev, "ASoC: failed to init %s\n", in soc_tplg_dbytes_create()
810 be->hdr.name); in soc_tplg_dbytes_create()
817 &sbe->dobj.control.kcontrol); in soc_tplg_dbytes_create()
819 dev_err(tplg->dev, "ASoC: failed to add %s\n", in soc_tplg_dbytes_create()
820 be->hdr.name); in soc_tplg_dbytes_create()
825 list_add(&sbe->dobj.list, &tplg->comp->dobj_list); in soc_tplg_dbytes_create()
844 dev_err(tplg->dev, "ASoC: invalid count %d for controls\n", in soc_tplg_dmixer_create()
846 return -EINVAL; in soc_tplg_dmixer_create()
850 mc = (struct snd_soc_tplg_mixer_control *)tplg->pos; in soc_tplg_dmixer_create()
853 if (strnlen(mc->hdr.name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN) == in soc_tplg_dmixer_create()
855 return -EINVAL; in soc_tplg_dmixer_create()
859 return -ENOMEM; in soc_tplg_dmixer_create()
860 tplg->pos += (sizeof(struct snd_soc_tplg_mixer_control) + in soc_tplg_dmixer_create()
861 le32_to_cpu(mc->priv.size)); in soc_tplg_dmixer_create()
863 dev_dbg(tplg->dev, in soc_tplg_dmixer_create()
865 mc->hdr.name, mc->hdr.access); in soc_tplg_dmixer_create()
868 kc.name = mc->hdr.name; in soc_tplg_dmixer_create()
871 kc.access = le32_to_cpu(mc->hdr.access); in soc_tplg_dmixer_create()
874 sm->reg = tplc_chan_get_reg(tplg, mc->channel, in soc_tplg_dmixer_create()
876 sm->rreg = tplc_chan_get_reg(tplg, mc->channel, in soc_tplg_dmixer_create()
878 sm->shift = tplc_chan_get_shift(tplg, mc->channel, in soc_tplg_dmixer_create()
880 sm->rshift = tplc_chan_get_shift(tplg, mc->channel, in soc_tplg_dmixer_create()
883 sm->max = le32_to_cpu(mc->max); in soc_tplg_dmixer_create()
884 sm->min = le32_to_cpu(mc->min); in soc_tplg_dmixer_create()
885 sm->invert = le32_to_cpu(mc->invert); in soc_tplg_dmixer_create()
886 sm->platform_max = le32_to_cpu(mc->platform_max); in soc_tplg_dmixer_create()
887 sm->dobj.index = tplg->index; in soc_tplg_dmixer_create()
888 sm->dobj.ops = tplg->ops; in soc_tplg_dmixer_create()
889 sm->dobj.type = SND_SOC_DOBJ_MIXER; in soc_tplg_dmixer_create()
890 INIT_LIST_HEAD(&sm->dobj.list); in soc_tplg_dmixer_create()
893 err = soc_tplg_kcontrol_bind_io(&mc->hdr, &kc, tplg); in soc_tplg_dmixer_create()
895 soc_control_err(tplg, &mc->hdr, mc->hdr.name); in soc_tplg_dmixer_create()
901 err = soc_tplg_create_tlv(tplg, &kc, &mc->hdr); in soc_tplg_dmixer_create()
903 dev_err(tplg->dev, "ASoC: failed to create TLV %s\n", in soc_tplg_dmixer_create()
904 mc->hdr.name); in soc_tplg_dmixer_create()
913 dev_err(tplg->dev, "ASoC: failed to init %s\n", in soc_tplg_dmixer_create()
914 mc->hdr.name); in soc_tplg_dmixer_create()
922 &sm->dobj.control.kcontrol); in soc_tplg_dmixer_create()
924 dev_err(tplg->dev, "ASoC: failed to add %s\n", in soc_tplg_dmixer_create()
925 mc->hdr.name); in soc_tplg_dmixer_create()
931 list_add(&sm->dobj.list, &tplg->comp->dobj_list); in soc_tplg_dmixer_create()
942 se->dobj.control.dtexts = in soc_tplg_denum_create_texts()
943 kcalloc(le32_to_cpu(ec->items), sizeof(char *), GFP_KERNEL); in soc_tplg_denum_create_texts()
944 if (se->dobj.control.dtexts == NULL) in soc_tplg_denum_create_texts()
945 return -ENOMEM; in soc_tplg_denum_create_texts()
947 for (i = 0; i < le32_to_cpu(ec->items); i++) { in soc_tplg_denum_create_texts()
949 if (strnlen(ec->texts[i], SNDRV_CTL_ELEM_ID_NAME_MAXLEN) == in soc_tplg_denum_create_texts()
951 ret = -EINVAL; in soc_tplg_denum_create_texts()
955 se->dobj.control.dtexts[i] = kstrdup(ec->texts[i], GFP_KERNEL); in soc_tplg_denum_create_texts()
956 if (!se->dobj.control.dtexts[i]) { in soc_tplg_denum_create_texts()
957 ret = -ENOMEM; in soc_tplg_denum_create_texts()
962 se->items = le32_to_cpu(ec->items); in soc_tplg_denum_create_texts()
963 se->texts = (const char * const *)se->dobj.control.dtexts; in soc_tplg_denum_create_texts()
967 se->items = i; in soc_tplg_denum_create_texts()
974 int i = se->items; in soc_tplg_denum_remove_texts()
976 for (--i; i >= 0; i--) in soc_tplg_denum_remove_texts()
977 kfree(se->dobj.control.dtexts[i]); in soc_tplg_denum_remove_texts()
978 kfree(se->dobj.control.dtexts); in soc_tplg_denum_remove_texts()
986 if (le32_to_cpu(ec->items) > sizeof(*ec->values)) in soc_tplg_denum_create_values()
987 return -EINVAL; in soc_tplg_denum_create_values()
989 se->dobj.control.dvalues = kzalloc(le32_to_cpu(ec->items) * in soc_tplg_denum_create_values()
992 if (!se->dobj.control.dvalues) in soc_tplg_denum_create_values()
993 return -ENOMEM; in soc_tplg_denum_create_values()
995 /* convert from little-endian */ in soc_tplg_denum_create_values()
996 for (i = 0; i < le32_to_cpu(ec->items); i++) { in soc_tplg_denum_create_values()
997 se->dobj.control.dvalues[i] = le32_to_cpu(ec->values[i]); in soc_tplg_denum_create_values()
1005 kfree(se->dobj.control.dvalues); in soc_tplg_denum_remove_values()
1021 dev_err(tplg->dev, "ASoC: invalid count %d for enum controls\n", in soc_tplg_denum_create()
1023 return -EINVAL; in soc_tplg_denum_create()
1027 ec = (struct snd_soc_tplg_enum_control *)tplg->pos; in soc_tplg_denum_create()
1030 if (strnlen(ec->hdr.name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN) == in soc_tplg_denum_create()
1032 return -EINVAL; in soc_tplg_denum_create()
1036 return -ENOMEM; in soc_tplg_denum_create()
1038 tplg->pos += (sizeof(struct snd_soc_tplg_enum_control) + in soc_tplg_denum_create()
1039 le32_to_cpu(ec->priv.size)); in soc_tplg_denum_create()
1041 dev_dbg(tplg->dev, "ASoC: adding enum kcontrol %s size %d\n", in soc_tplg_denum_create()
1042 ec->hdr.name, ec->items); in soc_tplg_denum_create()
1045 kc.name = ec->hdr.name; in soc_tplg_denum_create()
1048 kc.access = le32_to_cpu(ec->hdr.access); in soc_tplg_denum_create()
1050 se->reg = tplc_chan_get_reg(tplg, ec->channel, SNDRV_CHMAP_FL); in soc_tplg_denum_create()
1051 se->shift_l = tplc_chan_get_shift(tplg, ec->channel, in soc_tplg_denum_create()
1053 se->shift_r = tplc_chan_get_shift(tplg, ec->channel, in soc_tplg_denum_create()
1056 se->mask = le32_to_cpu(ec->mask); in soc_tplg_denum_create()
1057 se->dobj.index = tplg->index; in soc_tplg_denum_create()
1058 se->dobj.type = SND_SOC_DOBJ_ENUM; in soc_tplg_denum_create()
1059 se->dobj.ops = tplg->ops; in soc_tplg_denum_create()
1060 INIT_LIST_HEAD(&se->dobj.list); in soc_tplg_denum_create()
1062 switch (le32_to_cpu(ec->hdr.ops.info)) { in soc_tplg_denum_create()
1067 dev_err(tplg->dev, in soc_tplg_denum_create()
1069 ec->hdr.name); in soc_tplg_denum_create()
1078 dev_err(tplg->dev, in soc_tplg_denum_create()
1080 ec->hdr.name); in soc_tplg_denum_create()
1085 err = -EINVAL; in soc_tplg_denum_create()
1086 dev_err(tplg->dev, in soc_tplg_denum_create()
1088 ec->hdr.ops.info, ec->hdr.name); in soc_tplg_denum_create()
1093 err = soc_tplg_kcontrol_bind_io(&ec->hdr, &kc, tplg); in soc_tplg_denum_create()
1095 soc_control_err(tplg, &ec->hdr, ec->hdr.name); in soc_tplg_denum_create()
1103 dev_err(tplg->dev, "ASoC: failed to init %s\n", in soc_tplg_denum_create()
1104 ec->hdr.name); in soc_tplg_denum_create()
1110 &kc, &se->dobj.control.kcontrol); in soc_tplg_denum_create()
1112 dev_err(tplg->dev, "ASoC: could not add kcontrol %s\n", in soc_tplg_denum_create()
1113 ec->hdr.name); in soc_tplg_denum_create()
1117 list_add(&se->dobj.list, &tplg->comp->dobj_list); in soc_tplg_denum_create()
1133 dev_dbg(tplg->dev, "ASoC: adding %d kcontrols at 0x%lx\n", hdr->count, in soc_tplg_kcontrol_elems_load()
1136 for (i = 0; i < le32_to_cpu(hdr->count); i++) { in soc_tplg_kcontrol_elems_load()
1138 control_hdr = (struct snd_soc_tplg_ctl_hdr *)tplg->pos; in soc_tplg_kcontrol_elems_load()
1140 if (le32_to_cpu(control_hdr->size) != sizeof(*control_hdr)) { in soc_tplg_kcontrol_elems_load()
1141 dev_err(tplg->dev, "ASoC: invalid control size\n"); in soc_tplg_kcontrol_elems_load()
1142 return -EINVAL; in soc_tplg_kcontrol_elems_load()
1145 switch (le32_to_cpu(control_hdr->ops.info)) { in soc_tplg_kcontrol_elems_load()
1154 le32_to_cpu(hdr->payload_size)); in soc_tplg_kcontrol_elems_load()
1162 le32_to_cpu(hdr->payload_size)); in soc_tplg_kcontrol_elems_load()
1166 le32_to_cpu(hdr->payload_size)); in soc_tplg_kcontrol_elems_load()
1170 return -EINVAL; in soc_tplg_kcontrol_elems_load()
1173 dev_err(tplg->dev, "ASoC: invalid control\n"); in soc_tplg_kcontrol_elems_load()
1186 if (tplg->ops && tplg->ops->dapm_route_load) in soc_tplg_add_route()
1187 return tplg->ops->dapm_route_load(tplg->comp, tplg->index, in soc_tplg_add_route()
1196 struct snd_soc_dapm_context *dapm = &tplg->comp->dapm; in soc_tplg_dapm_graph_elems_load()
1202 count = le32_to_cpu(hdr->count); in soc_tplg_dapm_graph_elems_load()
1206 count, le32_to_cpu(hdr->payload_size), "graph")) { in soc_tplg_dapm_graph_elems_load()
1208 dev_err(tplg->dev, "ASoC: invalid count %d for DAPM routes\n", in soc_tplg_dapm_graph_elems_load()
1210 return -EINVAL; in soc_tplg_dapm_graph_elems_load()
1213 dev_dbg(tplg->dev, "ASoC: adding %d DAPM routes for index %d\n", count, in soc_tplg_dapm_graph_elems_load()
1214 hdr->index); in soc_tplg_dapm_graph_elems_load()
1220 return -ENOMEM; in soc_tplg_dapm_graph_elems_load()
1235 return -ENOMEM; in soc_tplg_dapm_graph_elems_load()
1240 elem = (struct snd_soc_tplg_dapm_graph_elem *)tplg->pos; in soc_tplg_dapm_graph_elems_load()
1241 tplg->pos += sizeof(struct snd_soc_tplg_dapm_graph_elem); in soc_tplg_dapm_graph_elems_load()
1244 if (strnlen(elem->source, SNDRV_CTL_ELEM_ID_NAME_MAXLEN) == in soc_tplg_dapm_graph_elems_load()
1246 ret = -EINVAL; in soc_tplg_dapm_graph_elems_load()
1249 if (strnlen(elem->sink, SNDRV_CTL_ELEM_ID_NAME_MAXLEN) == in soc_tplg_dapm_graph_elems_load()
1251 ret = -EINVAL; in soc_tplg_dapm_graph_elems_load()
1254 if (strnlen(elem->control, SNDRV_CTL_ELEM_ID_NAME_MAXLEN) == in soc_tplg_dapm_graph_elems_load()
1256 ret = -EINVAL; in soc_tplg_dapm_graph_elems_load()
1260 routes[i]->source = elem->source; in soc_tplg_dapm_graph_elems_load()
1261 routes[i]->sink = elem->sink; in soc_tplg_dapm_graph_elems_load()
1264 routes[i]->connected = NULL; in soc_tplg_dapm_graph_elems_load()
1265 if (strnlen(elem->control, SNDRV_CTL_ELEM_ID_NAME_MAXLEN) == 0) in soc_tplg_dapm_graph_elems_load()
1266 routes[i]->control = NULL; in soc_tplg_dapm_graph_elems_load()
1268 routes[i]->control = elem->control; in soc_tplg_dapm_graph_elems_load()
1271 routes[i]->dobj.type = SND_SOC_DOBJ_GRAPH; in soc_tplg_dapm_graph_elems_load()
1272 routes[i]->dobj.ops = tplg->ops; in soc_tplg_dapm_graph_elems_load()
1273 routes[i]->dobj.index = tplg->index; in soc_tplg_dapm_graph_elems_load()
1274 list_add(&routes[i]->dobj.list, &tplg->comp->dobj_list); in soc_tplg_dapm_graph_elems_load()
1278 dev_err(tplg->dev, "ASoC: topology: add_route failed: %d\n", ret); in soc_tplg_dapm_graph_elems_load()
1325 mc = (struct snd_soc_tplg_mixer_control *)tplg->pos; in soc_tplg_dapm_widget_dmixer_create()
1328 if (strnlen(mc->hdr.name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN) == in soc_tplg_dapm_widget_dmixer_create()
1336 tplg->pos += (sizeof(struct snd_soc_tplg_mixer_control) + in soc_tplg_dapm_widget_dmixer_create()
1337 le32_to_cpu(mc->priv.size)); in soc_tplg_dapm_widget_dmixer_create()
1339 dev_dbg(tplg->dev, " adding DAPM widget mixer control %s at %d\n", in soc_tplg_dapm_widget_dmixer_create()
1340 mc->hdr.name, i); in soc_tplg_dapm_widget_dmixer_create()
1343 kc[i].name = kstrdup(mc->hdr.name, GFP_KERNEL); in soc_tplg_dapm_widget_dmixer_create()
1347 kc[i].access = le32_to_cpu(mc->hdr.access); in soc_tplg_dapm_widget_dmixer_create()
1350 sm->reg = tplc_chan_get_reg(tplg, mc->channel, in soc_tplg_dapm_widget_dmixer_create()
1352 sm->rreg = tplc_chan_get_reg(tplg, mc->channel, in soc_tplg_dapm_widget_dmixer_create()
1354 sm->shift = tplc_chan_get_shift(tplg, mc->channel, in soc_tplg_dapm_widget_dmixer_create()
1356 sm->rshift = tplc_chan_get_shift(tplg, mc->channel, in soc_tplg_dapm_widget_dmixer_create()
1359 sm->max = le32_to_cpu(mc->max); in soc_tplg_dapm_widget_dmixer_create()
1360 sm->min = le32_to_cpu(mc->min); in soc_tplg_dapm_widget_dmixer_create()
1361 sm->invert = le32_to_cpu(mc->invert); in soc_tplg_dapm_widget_dmixer_create()
1362 sm->platform_max = le32_to_cpu(mc->platform_max); in soc_tplg_dapm_widget_dmixer_create()
1363 sm->dobj.index = tplg->index; in soc_tplg_dapm_widget_dmixer_create()
1364 INIT_LIST_HEAD(&sm->dobj.list); in soc_tplg_dapm_widget_dmixer_create()
1367 err = soc_tplg_kcontrol_bind_io(&mc->hdr, &kc[i], tplg); in soc_tplg_dapm_widget_dmixer_create()
1369 soc_control_err(tplg, &mc->hdr, mc->hdr.name); in soc_tplg_dapm_widget_dmixer_create()
1374 err = soc_tplg_create_tlv(tplg, &kc[i], &mc->hdr); in soc_tplg_dapm_widget_dmixer_create()
1376 dev_err(tplg->dev, "ASoC: failed to create TLV %s\n", in soc_tplg_dapm_widget_dmixer_create()
1377 mc->hdr.name); in soc_tplg_dapm_widget_dmixer_create()
1385 dev_err(tplg->dev, "ASoC: failed to init %s\n", in soc_tplg_dapm_widget_dmixer_create()
1386 mc->hdr.name); in soc_tplg_dapm_widget_dmixer_create()
1393 for (; i >= 0; i--) { in soc_tplg_dapm_widget_dmixer_create()
1417 ec = (struct snd_soc_tplg_enum_control *)tplg->pos; in soc_tplg_dapm_widget_denum_create()
1419 if (strnlen(ec->hdr.name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN) == in soc_tplg_dapm_widget_denum_create()
1427 tplg->pos += (sizeof(struct snd_soc_tplg_enum_control) + in soc_tplg_dapm_widget_denum_create()
1428 le32_to_cpu(ec->priv.size)); in soc_tplg_dapm_widget_denum_create()
1430 dev_dbg(tplg->dev, " adding DAPM widget enum control %s\n", in soc_tplg_dapm_widget_denum_create()
1431 ec->hdr.name); in soc_tplg_dapm_widget_denum_create()
1434 kc[i].name = kstrdup(ec->hdr.name, GFP_KERNEL); in soc_tplg_dapm_widget_denum_create()
1438 kc[i].access = le32_to_cpu(ec->hdr.access); in soc_tplg_dapm_widget_denum_create()
1441 se->reg = tplc_chan_get_reg(tplg, ec->channel, SNDRV_CHMAP_FL); in soc_tplg_dapm_widget_denum_create()
1442 se->shift_l = tplc_chan_get_shift(tplg, ec->channel, in soc_tplg_dapm_widget_denum_create()
1444 se->shift_r = tplc_chan_get_shift(tplg, ec->channel, in soc_tplg_dapm_widget_denum_create()
1447 se->items = le32_to_cpu(ec->items); in soc_tplg_dapm_widget_denum_create()
1448 se->mask = le32_to_cpu(ec->mask); in soc_tplg_dapm_widget_denum_create()
1449 se->dobj.index = tplg->index; in soc_tplg_dapm_widget_denum_create()
1451 switch (le32_to_cpu(ec->hdr.ops.info)) { in soc_tplg_dapm_widget_denum_create()
1456 dev_err(tplg->dev, "ASoC: could not create values for %s\n", in soc_tplg_dapm_widget_denum_create()
1457 ec->hdr.name); in soc_tplg_dapm_widget_denum_create()
1466 dev_err(tplg->dev, "ASoC: could not create texts for %s\n", in soc_tplg_dapm_widget_denum_create()
1467 ec->hdr.name); in soc_tplg_dapm_widget_denum_create()
1472 dev_err(tplg->dev, "ASoC: invalid enum control type %d for %s\n", in soc_tplg_dapm_widget_denum_create()
1473 ec->hdr.ops.info, ec->hdr.name); in soc_tplg_dapm_widget_denum_create()
1478 err = soc_tplg_kcontrol_bind_io(&ec->hdr, &kc[i], tplg); in soc_tplg_dapm_widget_denum_create()
1480 soc_control_err(tplg, &ec->hdr, ec->hdr.name); in soc_tplg_dapm_widget_denum_create()
1488 dev_err(tplg->dev, "ASoC: failed to init %s\n", in soc_tplg_dapm_widget_denum_create()
1489 ec->hdr.name); in soc_tplg_dapm_widget_denum_create()
1497 for (; i >= 0; i--) { in soc_tplg_dapm_widget_denum_create()
1527 be = (struct snd_soc_tplg_bytes_control *)tplg->pos; in soc_tplg_dapm_widget_dbytes_create()
1530 if (strnlen(be->hdr.name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN) == in soc_tplg_dapm_widget_dbytes_create()
1538 tplg->pos += (sizeof(struct snd_soc_tplg_bytes_control) + in soc_tplg_dapm_widget_dbytes_create()
1539 le32_to_cpu(be->priv.size)); in soc_tplg_dapm_widget_dbytes_create()
1541 dev_dbg(tplg->dev, in soc_tplg_dapm_widget_dbytes_create()
1543 be->hdr.name, be->hdr.access); in soc_tplg_dapm_widget_dbytes_create()
1546 kc[i].name = kstrdup(be->hdr.name, GFP_KERNEL); in soc_tplg_dapm_widget_dbytes_create()
1550 kc[i].access = le32_to_cpu(be->hdr.access); in soc_tplg_dapm_widget_dbytes_create()
1552 sbe->max = le32_to_cpu(be->max); in soc_tplg_dapm_widget_dbytes_create()
1553 INIT_LIST_HEAD(&sbe->dobj.list); in soc_tplg_dapm_widget_dbytes_create()
1556 err = soc_tplg_kcontrol_bind_io(&be->hdr, &kc[i], tplg); in soc_tplg_dapm_widget_dbytes_create()
1558 soc_control_err(tplg, &be->hdr, be->hdr.name); in soc_tplg_dapm_widget_dbytes_create()
1566 dev_err(tplg->dev, "ASoC: failed to init %s\n", in soc_tplg_dapm_widget_dbytes_create()
1567 be->hdr.name); in soc_tplg_dapm_widget_dbytes_create()
1575 for (; i >= 0; i--) { in soc_tplg_dapm_widget_dbytes_create()
1588 struct snd_soc_dapm_context *dapm = &tplg->comp->dapm; in soc_tplg_dapm_widget_create()
1591 struct snd_soc_card *card = tplg->comp->card; in soc_tplg_dapm_widget_create()
1595 if (strnlen(w->name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN) == in soc_tplg_dapm_widget_create()
1597 return -EINVAL; in soc_tplg_dapm_widget_create()
1598 if (strnlen(w->sname, SNDRV_CTL_ELEM_ID_NAME_MAXLEN) == in soc_tplg_dapm_widget_create()
1600 return -EINVAL; in soc_tplg_dapm_widget_create()
1602 dev_dbg(tplg->dev, "ASoC: creating DAPM widget %s id %d\n", in soc_tplg_dapm_widget_create()
1603 w->name, w->id); in soc_tplg_dapm_widget_create()
1608 template.id = get_widget_id(le32_to_cpu(w->id)); in soc_tplg_dapm_widget_create()
1613 template.name = kstrdup(w->name, GFP_KERNEL); in soc_tplg_dapm_widget_create()
1615 return -ENOMEM; in soc_tplg_dapm_widget_create()
1616 template.sname = kstrdup(w->sname, GFP_KERNEL); in soc_tplg_dapm_widget_create()
1618 ret = -ENOMEM; in soc_tplg_dapm_widget_create()
1621 template.reg = le32_to_cpu(w->reg); in soc_tplg_dapm_widget_create()
1622 template.shift = le32_to_cpu(w->shift); in soc_tplg_dapm_widget_create()
1623 template.mask = le32_to_cpu(w->mask); in soc_tplg_dapm_widget_create()
1624 template.subseq = le32_to_cpu(w->subseq); in soc_tplg_dapm_widget_create()
1625 template.on_val = w->invert ? 0 : 1; in soc_tplg_dapm_widget_create()
1626 template.off_val = w->invert ? 1 : 0; in soc_tplg_dapm_widget_create()
1627 template.ignore_suspend = le32_to_cpu(w->ignore_suspend); in soc_tplg_dapm_widget_create()
1628 template.event_flags = le16_to_cpu(w->event_flags); in soc_tplg_dapm_widget_create()
1629 template.dobj.index = tplg->index; in soc_tplg_dapm_widget_create()
1631 tplg->pos += in soc_tplg_dapm_widget_create()
1633 le32_to_cpu(w->priv.size)); in soc_tplg_dapm_widget_create()
1635 if (w->num_kcontrols == 0) { in soc_tplg_dapm_widget_create()
1641 control_hdr = (struct snd_soc_tplg_ctl_hdr *)tplg->pos; in soc_tplg_dapm_widget_create()
1642 dev_dbg(tplg->dev, "ASoC: template %s has %d controls of type %x\n", in soc_tplg_dapm_widget_create()
1643 w->name, w->num_kcontrols, control_hdr->type); in soc_tplg_dapm_widget_create()
1645 switch (le32_to_cpu(control_hdr->ops.info)) { in soc_tplg_dapm_widget_create()
1653 template.num_kcontrols = le32_to_cpu(w->num_kcontrols); in soc_tplg_dapm_widget_create()
1658 ret = -ENOMEM; in soc_tplg_dapm_widget_create()
1668 template.num_kcontrols = le32_to_cpu(w->num_kcontrols); in soc_tplg_dapm_widget_create()
1673 ret = -ENOMEM; in soc_tplg_dapm_widget_create()
1679 template.num_kcontrols = le32_to_cpu(w->num_kcontrols); in soc_tplg_dapm_widget_create()
1684 ret = -ENOMEM; in soc_tplg_dapm_widget_create()
1689 dev_err(tplg->dev, "ASoC: invalid widget control type %d:%d:%d\n", in soc_tplg_dapm_widget_create()
1690 control_hdr->ops.get, control_hdr->ops.put, in soc_tplg_dapm_widget_create()
1691 le32_to_cpu(control_hdr->ops.info)); in soc_tplg_dapm_widget_create()
1692 ret = -EINVAL; in soc_tplg_dapm_widget_create()
1703 if (card->instantiated) in soc_tplg_dapm_widget_create()
1712 widget->dobj.type = SND_SOC_DOBJ_WIDGET; in soc_tplg_dapm_widget_create()
1713 widget->dobj.widget.kcontrol_type = kcontrol_type; in soc_tplg_dapm_widget_create()
1714 widget->dobj.ops = tplg->ops; in soc_tplg_dapm_widget_create()
1715 widget->dobj.index = tplg->index; in soc_tplg_dapm_widget_create()
1716 list_add(&widget->dobj.list, &tplg->comp->dobj_list); in soc_tplg_dapm_widget_create()
1743 count = le32_to_cpu(hdr->count); in soc_tplg_dapm_widget_elems_load()
1745 dev_dbg(tplg->dev, "ASoC: adding %d DAPM widgets\n", count); in soc_tplg_dapm_widget_elems_load()
1748 widget = (struct snd_soc_tplg_dapm_widget *) tplg->pos; in soc_tplg_dapm_widget_elems_load()
1749 if (le32_to_cpu(widget->size) != sizeof(*widget)) { in soc_tplg_dapm_widget_elems_load()
1750 dev_err(tplg->dev, "ASoC: invalid widget size\n"); in soc_tplg_dapm_widget_elems_load()
1751 return -EINVAL; in soc_tplg_dapm_widget_elems_load()
1756 dev_err(tplg->dev, "ASoC: failed to load widget %s\n", in soc_tplg_dapm_widget_elems_load()
1757 widget->name); in soc_tplg_dapm_widget_elems_load()
1767 struct snd_soc_card *card = tplg->comp->card; in soc_tplg_dapm_complete()
1773 if (!card || !card->instantiated) { in soc_tplg_dapm_complete()
1774 dev_warn(tplg->dev, "ASoC: Parent card not yet available," in soc_tplg_dapm_complete()
1781 dev_err(tplg->dev, "ASoC: failed to create new widgets %d\n", in soc_tplg_dapm_complete()
1787 static int set_stream_info(struct snd_soc_pcm_stream *stream, in set_stream_info() argument
1790 stream->stream_name = kstrdup(caps->name, GFP_KERNEL); in set_stream_info()
1791 if (!stream->stream_name) in set_stream_info()
1792 return -ENOMEM; in set_stream_info()
1794 stream->channels_min = le32_to_cpu(caps->channels_min); in set_stream_info()
1795 stream->channels_max = le32_to_cpu(caps->channels_max); in set_stream_info()
1796 stream->rates = le32_to_cpu(caps->rates); in set_stream_info()
1797 stream->rate_min = le32_to_cpu(caps->rate_min); in set_stream_info()
1798 stream->rate_max = le32_to_cpu(caps->rate_max); in set_stream_info()
1799 stream->formats = le64_to_cpu(caps->formats); in set_stream_info()
1800 stream->sig_bits = le32_to_cpu(caps->sig_bits); in set_stream_info()
1809 dai_drv->symmetric_rates = in set_dai_flags()
1813 dai_drv->symmetric_channels = in set_dai_flags()
1818 dai_drv->symmetric_samplebits = in set_dai_flags()
1827 struct snd_soc_pcm_stream *stream; in soc_tplg_dai_create() local
1831 snd_soc_component_get_dapm(tplg->comp); in soc_tplg_dai_create()
1836 return -ENOMEM; in soc_tplg_dai_create()
1838 if (strlen(pcm->dai_name)) { in soc_tplg_dai_create()
1839 dai_drv->name = kstrdup(pcm->dai_name, GFP_KERNEL); in soc_tplg_dai_create()
1840 if (!dai_drv->name) { in soc_tplg_dai_create()
1841 ret = -ENOMEM; in soc_tplg_dai_create()
1845 dai_drv->id = le32_to_cpu(pcm->dai_id); in soc_tplg_dai_create()
1847 if (pcm->playback) { in soc_tplg_dai_create()
1848 stream = &dai_drv->playback; in soc_tplg_dai_create()
1849 caps = &pcm->caps[SND_SOC_TPLG_STREAM_PLAYBACK]; in soc_tplg_dai_create()
1850 ret = set_stream_info(stream, caps); in soc_tplg_dai_create()
1855 if (pcm->capture) { in soc_tplg_dai_create()
1856 stream = &dai_drv->capture; in soc_tplg_dai_create()
1857 caps = &pcm->caps[SND_SOC_TPLG_STREAM_CAPTURE]; in soc_tplg_dai_create()
1858 ret = set_stream_info(stream, caps); in soc_tplg_dai_create()
1863 if (pcm->compress) in soc_tplg_dai_create()
1864 dai_drv->compress_new = snd_soc_new_compress; in soc_tplg_dai_create()
1869 dev_err(tplg->comp->dev, "ASoC: DAI loading failed\n"); in soc_tplg_dai_create()
1873 dai_drv->dobj.index = tplg->index; in soc_tplg_dai_create()
1874 dai_drv->dobj.ops = tplg->ops; in soc_tplg_dai_create()
1875 dai_drv->dobj.type = SND_SOC_DOBJ_PCM; in soc_tplg_dai_create()
1876 list_add(&dai_drv->dobj.list, &tplg->comp->dobj_list); in soc_tplg_dai_create()
1879 dai = devm_snd_soc_register_dai(tplg->comp->dev, tplg->comp, dai_drv, false); in soc_tplg_dai_create()
1881 return -ENOMEM; in soc_tplg_dai_create()
1886 dev_err(dai->dev, "Failed to create DAI widgets %d\n", ret); in soc_tplg_dai_create()
1893 kfree(dai_drv->playback.stream_name); in soc_tplg_dai_create()
1894 kfree(dai_drv->capture.stream_name); in soc_tplg_dai_create()
1895 kfree(dai_drv->name); in soc_tplg_dai_create()
1905 link->symmetric_rates = in set_link_flags()
1909 link->symmetric_channels = in set_link_flags()
1914 link->symmetric_samplebits = in set_link_flags()
1919 link->ignore_suspend = in set_link_flags()
1935 return -ENOMEM; in soc_tplg_fe_link_create()
1939 link->cpus = &dlc[0]; in soc_tplg_fe_link_create()
1940 link->codecs = &dlc[1]; in soc_tplg_fe_link_create()
1941 link->platforms = &dlc[2]; in soc_tplg_fe_link_create()
1943 link->num_cpus = 1; in soc_tplg_fe_link_create()
1944 link->num_codecs = 1; in soc_tplg_fe_link_create()
1945 link->num_platforms = 1; in soc_tplg_fe_link_create()
1947 link->dobj.index = tplg->index; in soc_tplg_fe_link_create()
1948 link->dobj.ops = tplg->ops; in soc_tplg_fe_link_create()
1949 link->dobj.type = SND_SOC_DOBJ_DAI_LINK; in soc_tplg_fe_link_create()
1951 if (strlen(pcm->pcm_name)) { in soc_tplg_fe_link_create()
1952 link->name = kstrdup(pcm->pcm_name, GFP_KERNEL); in soc_tplg_fe_link_create()
1953 link->stream_name = kstrdup(pcm->pcm_name, GFP_KERNEL); in soc_tplg_fe_link_create()
1954 if (!link->name || !link->stream_name) { in soc_tplg_fe_link_create()
1955 ret = -ENOMEM; in soc_tplg_fe_link_create()
1959 link->id = le32_to_cpu(pcm->pcm_id); in soc_tplg_fe_link_create()
1961 if (strlen(pcm->dai_name)) { in soc_tplg_fe_link_create()
1962 link->cpus->dai_name = kstrdup(pcm->dai_name, GFP_KERNEL); in soc_tplg_fe_link_create()
1963 if (!link->cpus->dai_name) { in soc_tplg_fe_link_create()
1964 ret = -ENOMEM; in soc_tplg_fe_link_create()
1969 link->codecs->name = "snd-soc-dummy"; in soc_tplg_fe_link_create()
1970 link->codecs->dai_name = "snd-soc-dummy-dai"; in soc_tplg_fe_link_create()
1972 link->platforms->name = "snd-soc-dummy"; in soc_tplg_fe_link_create()
1975 link->dynamic = 1; in soc_tplg_fe_link_create()
1976 link->dpcm_playback = le32_to_cpu(pcm->playback); in soc_tplg_fe_link_create()
1977 link->dpcm_capture = le32_to_cpu(pcm->capture); in soc_tplg_fe_link_create()
1978 if (pcm->flag_mask) in soc_tplg_fe_link_create()
1980 le32_to_cpu(pcm->flag_mask), in soc_tplg_fe_link_create()
1981 le32_to_cpu(pcm->flags)); in soc_tplg_fe_link_create()
1986 dev_err(tplg->comp->dev, "ASoC: FE link loading failed\n"); in soc_tplg_fe_link_create()
1990 ret = snd_soc_add_pcm_runtime(tplg->comp->card, link); in soc_tplg_fe_link_create()
1992 dev_err(tplg->comp->dev, "ASoC: adding FE link failed\n"); in soc_tplg_fe_link_create()
1996 list_add(&link->dobj.list, &tplg->comp->dobj_list); in soc_tplg_fe_link_create()
2000 kfree(link->name); in soc_tplg_fe_link_create()
2001 kfree(link->stream_name); in soc_tplg_fe_link_create()
2002 kfree(link->cpus->dai_name); in soc_tplg_fe_link_create()
2020 /* copy stream caps from the old version 4 of source */
2024 dest->size = cpu_to_le32(sizeof(*dest)); in stream_caps_new_ver()
2025 memcpy(dest->name, src->name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN); in stream_caps_new_ver()
2026 dest->formats = src->formats; in stream_caps_new_ver()
2027 dest->rates = src->rates; in stream_caps_new_ver()
2028 dest->rate_min = src->rate_min; in stream_caps_new_ver()
2029 dest->rate_max = src->rate_max; in stream_caps_new_ver()
2030 dest->channels_min = src->channels_min; in stream_caps_new_ver()
2031 dest->channels_max = src->channels_max; in stream_caps_new_ver()
2032 dest->periods_min = src->periods_min; in stream_caps_new_ver()
2033 dest->periods_max = src->periods_max; in stream_caps_new_ver()
2034 dest->period_size_min = src->period_size_min; in stream_caps_new_ver()
2035 dest->period_size_max = src->period_size_max; in stream_caps_new_ver()
2036 dest->buffer_size_min = src->buffer_size_min; in stream_caps_new_ver()
2037 dest->buffer_size_max = src->buffer_size_max; in stream_caps_new_ver()
2041 * pcm_new_ver - Create the new version of PCM from the old version.
2058 if (le32_to_cpu(src->size) != sizeof(*src_v4)) { in pcm_new_ver()
2059 dev_err(tplg->dev, "ASoC: invalid PCM size\n"); in pcm_new_ver()
2060 return -EINVAL; in pcm_new_ver()
2063 dev_warn(tplg->dev, "ASoC: old version of PCM\n"); in pcm_new_ver()
2067 return -ENOMEM; in pcm_new_ver()
2069 dest->size = cpu_to_le32(sizeof(*dest)); /* size of latest abi version */ in pcm_new_ver()
2070 memcpy(dest->pcm_name, src_v4->pcm_name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN); in pcm_new_ver()
2071 memcpy(dest->dai_name, src_v4->dai_name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN); in pcm_new_ver()
2072 dest->pcm_id = src_v4->pcm_id; in pcm_new_ver()
2073 dest->dai_id = src_v4->dai_id; in pcm_new_ver()
2074 dest->playback = src_v4->playback; in pcm_new_ver()
2075 dest->capture = src_v4->capture; in pcm_new_ver()
2076 dest->compress = src_v4->compress; in pcm_new_ver()
2077 dest->num_streams = src_v4->num_streams; in pcm_new_ver()
2078 for (i = 0; i < le32_to_cpu(dest->num_streams); i++) in pcm_new_ver()
2079 memcpy(&dest->stream[i], &src_v4->stream[i], in pcm_new_ver()
2083 stream_caps_new_ver(&dest->caps[i], &src_v4->caps[i]); in pcm_new_ver()
2099 count = le32_to_cpu(hdr->count); in soc_tplg_pcm_elems_load()
2102 pcm = (struct snd_soc_tplg_pcm *)tplg->pos; in soc_tplg_pcm_elems_load()
2103 size = le32_to_cpu(pcm->size); in soc_tplg_pcm_elems_load()
2106 dev_err(tplg->dev, "ASoC: invalid size %d for PCM elems\n", in soc_tplg_pcm_elems_load()
2108 return -EINVAL; in soc_tplg_pcm_elems_load()
2113 le32_to_cpu(hdr->payload_size), in soc_tplg_pcm_elems_load()
2115 dev_err(tplg->dev, "ASoC: invalid count %d for PCM DAI elems\n", in soc_tplg_pcm_elems_load()
2117 return -EINVAL; in soc_tplg_pcm_elems_load()
2121 pcm = (struct snd_soc_tplg_pcm *)tplg->pos; in soc_tplg_pcm_elems_load()
2122 size = le32_to_cpu(pcm->size); in soc_tplg_pcm_elems_load()
2125 * if abi not match. in soc_tplg_pcm_elems_load()
2145 /* offset by version-specific struct size and in soc_tplg_pcm_elems_load()
2148 tplg->pos += size + le32_to_cpu(_pcm->priv.size); in soc_tplg_pcm_elems_load()
2154 dev_dbg(tplg->dev, "ASoC: adding %d PCM DAIs\n", count); in soc_tplg_pcm_elems_load()
2160 * set_link_hw_format - Set the HW audio format of the physical DAI link.
2176 for (i = 0; i < le32_to_cpu(cfg->num_hw_configs); i++) { in set_link_hw_format()
2177 hw_config = &cfg->hw_config[i]; in set_link_hw_format()
2178 if (hw_config->id != cfg->default_hw_config_id) in set_link_hw_format()
2181 link->dai_fmt = le32_to_cpu(hw_config->fmt) & in set_link_hw_format()
2185 switch (hw_config->clock_gated) { in set_link_hw_format()
2187 link->dai_fmt |= SND_SOC_DAIFMT_GATED; in set_link_hw_format()
2191 link->dai_fmt |= SND_SOC_DAIFMT_CONT; in set_link_hw_format()
2200 invert_bclk = hw_config->invert_bclk; in set_link_hw_format()
2201 invert_fsync = hw_config->invert_fsync; in set_link_hw_format()
2203 link->dai_fmt |= SND_SOC_DAIFMT_NB_NF; in set_link_hw_format()
2205 link->dai_fmt |= SND_SOC_DAIFMT_NB_IF; in set_link_hw_format()
2207 link->dai_fmt |= SND_SOC_DAIFMT_IB_NF; in set_link_hw_format()
2209 link->dai_fmt |= SND_SOC_DAIFMT_IB_IF; in set_link_hw_format()
2212 bclk_master = (hw_config->bclk_master == in set_link_hw_format()
2214 fsync_master = (hw_config->fsync_master == in set_link_hw_format()
2217 link->dai_fmt |= SND_SOC_DAIFMT_CBM_CFM; in set_link_hw_format()
2219 link->dai_fmt |= SND_SOC_DAIFMT_CBS_CFM; in set_link_hw_format()
2221 link->dai_fmt |= SND_SOC_DAIFMT_CBM_CFS; in set_link_hw_format()
2223 link->dai_fmt |= SND_SOC_DAIFMT_CBS_CFS; in set_link_hw_format()
2228 * link_new_ver - Create a new physical link config from the old
2246 if (le32_to_cpu(src->size) != in link_new_ver()
2248 dev_err(tplg->dev, "ASoC: invalid physical link config size\n"); in link_new_ver()
2249 return -EINVAL; in link_new_ver()
2252 dev_warn(tplg->dev, "ASoC: old version of physical link config\n"); in link_new_ver()
2257 return -ENOMEM; in link_new_ver()
2259 dest->size = cpu_to_le32(sizeof(*dest)); in link_new_ver()
2260 dest->id = src_v4->id; in link_new_ver()
2261 dest->num_streams = src_v4->num_streams; in link_new_ver()
2262 for (i = 0; i < le32_to_cpu(dest->num_streams); i++) in link_new_ver()
2263 memcpy(&dest->stream[i], &src_v4->stream[i], in link_new_ver()
2271 * snd_soc_find_dai_link - Find a DAI link
2274 * @id: DAI link ID to match
2275 * @name: DAI link name to match, optional
2276 * @stream_name: DAI link stream name to match, optional
2280 * unique ID, so name and stream name should also match if being
2293 link = rtd->dai_link; in snd_soc_find_dai_link()
2295 if (link->id != id) in snd_soc_find_dai_link()
2298 if (name && (!link->name || strcmp(name, link->name))) in snd_soc_find_dai_link()
2301 if (stream_name && (!link->stream_name in snd_soc_find_dai_link()
2302 || strcmp(stream_name, link->stream_name))) in snd_soc_find_dai_link()
2320 len = strnlen(cfg->name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN); in soc_tplg_link_config()
2322 return -EINVAL; in soc_tplg_link_config()
2324 name = cfg->name; in soc_tplg_link_config()
2328 len = strnlen(cfg->stream_name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN); in soc_tplg_link_config()
2330 return -EINVAL; in soc_tplg_link_config()
2332 stream_name = cfg->stream_name; in soc_tplg_link_config()
2336 link = snd_soc_find_dai_link(tplg->comp->card, le32_to_cpu(cfg->id), in soc_tplg_link_config()
2339 dev_err(tplg->dev, "ASoC: physical link %s (id %d) not exist\n", in soc_tplg_link_config()
2340 name, cfg->id); in soc_tplg_link_config()
2341 return -EINVAL; in soc_tplg_link_config()
2345 if (cfg->num_hw_configs) in soc_tplg_link_config()
2349 if (cfg->flag_mask) in soc_tplg_link_config()
2351 le32_to_cpu(cfg->flag_mask), in soc_tplg_link_config()
2352 le32_to_cpu(cfg->flags)); in soc_tplg_link_config()
2357 dev_err(tplg->dev, "ASoC: physical link loading failed\n"); in soc_tplg_link_config()
2362 link->dobj.index = tplg->index; in soc_tplg_link_config()
2363 link->dobj.ops = tplg->ops; in soc_tplg_link_config()
2364 link->dobj.type = SND_SOC_DOBJ_BACKEND_LINK; in soc_tplg_link_config()
2365 list_add(&link->dobj.list, &tplg->comp->dobj_list); in soc_tplg_link_config()
2381 count = le32_to_cpu(hdr->count); in soc_tplg_link_elems_load()
2384 link = (struct snd_soc_tplg_link_config *)tplg->pos; in soc_tplg_link_elems_load()
2385 size = le32_to_cpu(link->size); in soc_tplg_link_elems_load()
2388 dev_err(tplg->dev, "ASoC: invalid size %d for physical link elems\n", in soc_tplg_link_elems_load()
2390 return -EINVAL; in soc_tplg_link_elems_load()
2395 le32_to_cpu(hdr->payload_size), in soc_tplg_link_elems_load()
2397 dev_err(tplg->dev, "ASoC: invalid count %d for physical link elems\n", in soc_tplg_link_elems_load()
2399 return -EINVAL; in soc_tplg_link_elems_load()
2404 link = (struct snd_soc_tplg_link_config *)tplg->pos; in soc_tplg_link_elems_load()
2405 size = le32_to_cpu(link->size); in soc_tplg_link_elems_load()
2423 /* offset by version-specific struct size and in soc_tplg_link_elems_load()
2426 tplg->pos += size + le32_to_cpu(_link->priv.size); in soc_tplg_link_elems_load()
2436 * soc_tplg_dai_config - Find and configure an existing physical DAI.
2449 struct snd_soc_pcm_stream *stream; in soc_tplg_dai_config() local
2455 dai_component.dai_name = d->dai_name; in soc_tplg_dai_config()
2458 dev_err(tplg->dev, "ASoC: physical DAI %s not registered\n", in soc_tplg_dai_config()
2459 d->dai_name); in soc_tplg_dai_config()
2460 return -EINVAL; in soc_tplg_dai_config()
2463 if (le32_to_cpu(d->dai_id) != dai->id) { in soc_tplg_dai_config()
2464 dev_err(tplg->dev, "ASoC: physical DAI %s id mismatch\n", in soc_tplg_dai_config()
2465 d->dai_name); in soc_tplg_dai_config()
2466 return -EINVAL; in soc_tplg_dai_config()
2469 dai_drv = dai->driver; in soc_tplg_dai_config()
2471 return -EINVAL; in soc_tplg_dai_config()
2473 if (d->playback) { in soc_tplg_dai_config()
2474 stream = &dai_drv->playback; in soc_tplg_dai_config()
2475 caps = &d->caps[SND_SOC_TPLG_STREAM_PLAYBACK]; in soc_tplg_dai_config()
2476 ret = set_stream_info(stream, caps); in soc_tplg_dai_config()
2481 if (d->capture) { in soc_tplg_dai_config()
2482 stream = &dai_drv->capture; in soc_tplg_dai_config()
2483 caps = &d->caps[SND_SOC_TPLG_STREAM_CAPTURE]; in soc_tplg_dai_config()
2484 ret = set_stream_info(stream, caps); in soc_tplg_dai_config()
2489 if (d->flag_mask) in soc_tplg_dai_config()
2491 le32_to_cpu(d->flag_mask), in soc_tplg_dai_config()
2492 le32_to_cpu(d->flags)); in soc_tplg_dai_config()
2497 dev_err(tplg->comp->dev, "ASoC: DAI loading failed\n"); in soc_tplg_dai_config()
2504 kfree(dai_drv->playback.stream_name); in soc_tplg_dai_config()
2505 kfree(dai_drv->capture.stream_name); in soc_tplg_dai_config()
2517 count = le32_to_cpu(hdr->count); in soc_tplg_dai_elems_load()
2521 dai = (struct snd_soc_tplg_dai *)tplg->pos; in soc_tplg_dai_elems_load()
2522 if (le32_to_cpu(dai->size) != sizeof(*dai)) { in soc_tplg_dai_elems_load()
2523 dev_err(tplg->dev, "ASoC: invalid physical DAI size\n"); in soc_tplg_dai_elems_load()
2524 return -EINVAL; in soc_tplg_dai_elems_load()
2529 dev_err(tplg->dev, "ASoC: failed to configure DAI\n"); in soc_tplg_dai_elems_load()
2533 tplg->pos += (sizeof(*dai) + le32_to_cpu(dai->priv.size)); in soc_tplg_dai_elems_load()
2536 dev_dbg(tplg->dev, "ASoC: Configure %d BE DAIs\n", count); in soc_tplg_dai_elems_load()
2541 * manifest_new_ver - Create a new version of manifest from the old version
2559 size = le32_to_cpu(src->size); in manifest_new_ver()
2561 dev_warn(tplg->dev, "ASoC: invalid manifest size %d\n", in manifest_new_ver()
2564 return -EINVAL; in manifest_new_ver()
2565 src->size = cpu_to_le32(sizeof(*src_v4)); in manifest_new_ver()
2568 dev_warn(tplg->dev, "ASoC: old version of manifest\n"); in manifest_new_ver()
2571 dest = kzalloc(sizeof(*dest) + le32_to_cpu(src_v4->priv.size), in manifest_new_ver()
2574 return -ENOMEM; in manifest_new_ver()
2576 dest->size = cpu_to_le32(sizeof(*dest)); /* size of latest abi version */ in manifest_new_ver()
2577 dest->control_elems = src_v4->control_elems; in manifest_new_ver()
2578 dest->widget_elems = src_v4->widget_elems; in manifest_new_ver()
2579 dest->graph_elems = src_v4->graph_elems; in manifest_new_ver()
2580 dest->pcm_elems = src_v4->pcm_elems; in manifest_new_ver()
2581 dest->dai_link_elems = src_v4->dai_link_elems; in manifest_new_ver()
2582 dest->priv.size = src_v4->priv.size; in manifest_new_ver()
2583 if (dest->priv.size) in manifest_new_ver()
2584 memcpy(dest->priv.data, src_v4->priv.data, in manifest_new_ver()
2585 le32_to_cpu(src_v4->priv.size)); in manifest_new_ver()
2598 manifest = (struct snd_soc_tplg_manifest *)tplg->pos; in soc_tplg_manifest_load()
2600 /* check ABI version by size, create a new manifest if abi not match */ in soc_tplg_manifest_load()
2601 if (le32_to_cpu(manifest->size) == sizeof(*manifest)) { in soc_tplg_manifest_load()
2612 if (tplg->ops && tplg->ops->manifest) in soc_tplg_manifest_load()
2613 ret = tplg->ops->manifest(tplg->comp, tplg->index, _manifest); in soc_tplg_manifest_load()
2625 if (soc_tplg_get_hdr_offset(tplg) >= tplg->fw->size) in soc_valid_header()
2628 if (le32_to_cpu(hdr->size) != sizeof(*hdr)) { in soc_valid_header()
2629 dev_err(tplg->dev, in soc_valid_header()
2631 le32_to_cpu(hdr->type), soc_tplg_get_hdr_offset(tplg), in soc_valid_header()
2632 tplg->fw->size); in soc_valid_header()
2633 return -EINVAL; in soc_valid_header()
2637 if (le32_to_cpu(hdr->magic) == SOC_TPLG_MAGIC_BIG_ENDIAN) { in soc_valid_header()
2638 dev_err(tplg->dev, in soc_valid_header()
2640 tplg->pass, hdr->magic, in soc_valid_header()
2641 soc_tplg_get_hdr_offset(tplg), tplg->fw->size); in soc_valid_header()
2642 return -EINVAL; in soc_valid_header()
2645 if (le32_to_cpu(hdr->magic) != SND_SOC_TPLG_MAGIC) { in soc_valid_header()
2646 dev_err(tplg->dev, in soc_valid_header()
2648 tplg->pass, hdr->magic, in soc_valid_header()
2649 soc_tplg_get_hdr_offset(tplg), tplg->fw->size); in soc_valid_header()
2650 return -EINVAL; in soc_valid_header()
2654 if (le32_to_cpu(hdr->abi) > SND_SOC_TPLG_ABI_VERSION || in soc_valid_header()
2655 le32_to_cpu(hdr->abi) < SND_SOC_TPLG_ABI_VERSION_MIN) { in soc_valid_header()
2656 dev_err(tplg->dev, in soc_valid_header()
2658 tplg->pass, hdr->abi, in soc_valid_header()
2660 tplg->fw->size); in soc_valid_header()
2661 return -EINVAL; in soc_valid_header()
2664 if (hdr->payload_size == 0) { in soc_valid_header()
2665 dev_err(tplg->dev, "ASoC: header has 0 size at offset 0x%lx.\n", in soc_valid_header()
2667 return -EINVAL; in soc_valid_header()
2681 tplg->pos = tplg->hdr_pos + sizeof(struct snd_soc_tplg_hdr); in soc_tplg_load_header()
2684 if (le32_to_cpu(hdr->index) != tplg->req_index && in soc_tplg_load_header()
2685 tplg->req_index != SND_SOC_TPLG_INDEX_ALL) in soc_tplg_load_header()
2688 tplg->index = le32_to_cpu(hdr->index); in soc_tplg_load_header()
2690 switch (le32_to_cpu(hdr->type)) { in soc_tplg_load_header()
2730 if (tplg->pass == hdr_pass) { in soc_tplg_load_header()
2731 dev_dbg(tplg->dev, in soc_tplg_load_header()
2733 hdr->payload_size, hdr->type, hdr->version, in soc_tplg_load_header()
2734 hdr->vendor_type, tplg->pass); in soc_tplg_load_header()
2747 tplg->pass = SOC_TPLG_PASS_START; in soc_tplg_process_headers()
2750 while (tplg->pass <= SOC_TPLG_PASS_END) { in soc_tplg_process_headers()
2752 tplg->hdr_pos = tplg->fw->data; in soc_tplg_process_headers()
2753 hdr = (struct snd_soc_tplg_hdr *)tplg->hdr_pos; in soc_tplg_process_headers()
2760 dev_err(tplg->dev, in soc_tplg_process_headers()
2770 dev_err(tplg->dev, in soc_tplg_process_headers()
2776 tplg->hdr_pos += le32_to_cpu(hdr->payload_size) + in soc_tplg_process_headers()
2778 hdr = (struct snd_soc_tplg_hdr *)tplg->hdr_pos; in soc_tplg_process_headers()
2782 tplg->pass++; in soc_tplg_process_headers()
2788 dev_err(tplg->dev, in soc_tplg_process_headers()
2814 return -EINVAL; in snd_soc_tplg_component_load()
2819 tplg.dev = comp->dev; in snd_soc_tplg_component_load()
2823 tplg.io_ops = ops->io_ops; in snd_soc_tplg_component_load()
2824 tplg.io_ops_count = ops->io_ops_count; in snd_soc_tplg_component_load()
2825 tplg.bytes_ext_ops = ops->bytes_ext_ops; in snd_soc_tplg_component_load()
2826 tplg.bytes_ext_ops_count = ops->bytes_ext_ops_count; in snd_soc_tplg_component_load()
2841 if (w->dobj.type != SND_SOC_DOBJ_WIDGET) in snd_soc_tplg_widget_remove()
2844 remove_widget(w->dapm->component, &w->dobj, SOC_TPLG_PASS_WIDGET); in snd_soc_tplg_widget_remove()
2854 for_each_card_widgets_safe(dapm->card, w, next_w) { in snd_soc_tplg_widget_remove_all()
2857 if (w->dobj.type != SND_SOC_DOBJ_WIDGET || w->dapm != dapm) in snd_soc_tplg_widget_remove_all()
2860 /* match ID */ in snd_soc_tplg_widget_remove_all()
2861 if (w->dobj.index != index && in snd_soc_tplg_widget_remove_all()
2862 w->dobj.index != SND_SOC_TPLG_INDEX_ALL) in snd_soc_tplg_widget_remove_all()
2882 list_for_each_entry_safe(dobj, next_dobj, &comp->dobj_list, in snd_soc_tplg_component_remove()
2885 /* match index */ in snd_soc_tplg_component_remove()
2886 if (dobj->index != index && in snd_soc_tplg_component_remove()
2890 switch (dobj->type) { in snd_soc_tplg_component_remove()
2920 dev_err(comp->dev, "ASoC: invalid component type %d for removal\n", in snd_soc_tplg_component_remove()
2921 dobj->type); in snd_soc_tplg_component_remove()
2925 pass--; in snd_soc_tplg_component_remove()
2929 return !list_empty(&comp->dobj_list); in snd_soc_tplg_component_remove()