Lines Matching +full:be +full:- +full:dai +full:- +full:link
1 // SPDX-License-Identifier: GPL-2.0+
3 // soc-topology.c -- ALSA SoC Topology
17 // topology data can contain kcontrols, DAPM graphs, widgets, DAIs, DAI links,
29 #include <sound/soc-dapm.h>
30 #include <sound/soc-topology.h>
36 * We make several passes over the data (since it wont necessarily be ordered)
38 * drivers will be ready with any vendor data before the mixers and DAPM objects
83 const u8 *end = tplg->pos + elem_size * count; in soc_tplg_check_elem_count()
85 if (end > tplg->fw->data + tplg->fw->size) { in soc_tplg_check_elem_count()
86 dev_err(tplg->dev, "ASoC: %s overflow end of data\n", in soc_tplg_check_elem_count()
88 return -EINVAL; in soc_tplg_check_elem_count()
94 dev_err(tplg->dev, in soc_tplg_check_elem_count()
97 return -EINVAL; in soc_tplg_check_elem_count()
105 const u8 *end = tplg->hdr_pos; in soc_tplg_is_eof()
107 if (end >= tplg->fw->data + tplg->fw->size) in soc_tplg_is_eof()
114 return (unsigned long)(tplg->hdr_pos - tplg->fw->data); in soc_tplg_get_hdr_offset()
119 return (unsigned long)(tplg->pos - tplg->fw->data); in soc_tplg_get_offset()
195 return -EINVAL; in tplg_chan_get_reg()
208 return -EINVAL; in tplg_chan_get_shift()
220 return -EINVAL; in get_widget_id()
226 dev_err(tplg->dev, in soc_bind_err()
228 hdr->ops.get, hdr->ops.put, hdr->ops.info, index, in soc_bind_err()
235 dev_err(tplg->dev, in soc_control_err()
237 name, hdr->ops.get, hdr->ops.put, hdr->ops.info, in soc_control_err()
247 if (tplg->ops && tplg->ops->vendor_load) in soc_tplg_vendor_load()
248 ret = tplg->ops->vendor_load(tplg->comp, tplg->index, hdr); in soc_tplg_vendor_load()
250 dev_err(tplg->dev, "ASoC: no vendor load callback for ID %d\n", in soc_tplg_vendor_load()
251 hdr->vendor_type); in soc_tplg_vendor_load()
252 return -EINVAL; in soc_tplg_vendor_load()
256 dev_err(tplg->dev, in soc_tplg_vendor_load()
260 hdr->type, hdr->vendor_type); in soc_tplg_vendor_load()
269 if (tplg->ops && tplg->ops->widget_load) in soc_tplg_widget_load()
270 return tplg->ops->widget_load(tplg->comp, tplg->index, w, in soc_tplg_widget_load()
281 if (tplg->ops && tplg->ops->widget_ready) in soc_tplg_widget_ready()
282 return tplg->ops->widget_ready(tplg->comp, tplg->index, w, in soc_tplg_widget_ready()
288 /* pass DAI configurations to component driver for extra initialization */
291 struct snd_soc_tplg_pcm *pcm, struct snd_soc_dai *dai) in soc_tplg_dai_load() argument
293 if (tplg->ops && tplg->ops->dai_load) in soc_tplg_dai_load()
294 return tplg->ops->dai_load(tplg->comp, tplg->index, dai_drv, in soc_tplg_dai_load()
295 pcm, dai); in soc_tplg_dai_load()
300 /* pass link configurations to component driver for extra initialization */
302 struct snd_soc_dai_link *link, struct snd_soc_tplg_link_config *cfg) in soc_tplg_dai_link_load() argument
304 if (tplg->ops && tplg->ops->link_load) in soc_tplg_dai_link_load()
305 return tplg->ops->link_load(tplg->comp, tplg->index, link, cfg); in soc_tplg_dai_link_load()
313 if (tplg->ops && tplg->ops->complete) in soc_tplg_complete()
314 return tplg->ops->complete(tplg->comp); in soc_tplg_complete()
326 *kcontrol = snd_soc_cnew(control_new, data, control_new->name, prefix); in soc_tplg_add_dcontrol()
329 control_new->name); in soc_tplg_add_dcontrol()
330 return -ENOMEM; in soc_tplg_add_dcontrol()
336 control_new->name, err); in soc_tplg_add_dcontrol()
347 struct snd_soc_component *comp = tplg->comp; in soc_tplg_add_kcontrol()
349 return soc_tplg_add_dcontrol(comp->card->snd_card, in soc_tplg_add_kcontrol()
350 tplg->dev, k, comp->name_prefix, comp, kcontrol); in soc_tplg_add_kcontrol()
357 struct snd_card *card = comp->card->snd_card; in soc_tplg_remove_kcontrol()
362 if (dobj->unload) in soc_tplg_remove_kcontrol()
363 dobj->unload(comp, dobj); in soc_tplg_remove_kcontrol()
365 snd_ctl_remove(card, dobj->control.kcontrol); in soc_tplg_remove_kcontrol()
366 list_del(&dobj->list); in soc_tplg_remove_kcontrol()
376 if (dobj->unload) in soc_tplg_remove_route()
377 dobj->unload(comp, dobj); in soc_tplg_remove_route()
379 list_del(&dobj->list); in soc_tplg_remove_route()
382 /* remove a widget and it's kcontrols - routes must be removed first */
386 struct snd_card *card = comp->card->snd_card; in soc_tplg_remove_widget()
394 if (dobj->unload) in soc_tplg_remove_widget()
395 dobj->unload(comp, dobj); in soc_tplg_remove_widget()
397 if (!w->kcontrols) in soc_tplg_remove_widget()
400 for (i = 0; w->kcontrols && i < w->num_kcontrols; i++) in soc_tplg_remove_widget()
401 snd_ctl_remove(card, w->kcontrols[i]); in soc_tplg_remove_widget()
405 list_del(&dobj->list); in soc_tplg_remove_widget()
407 /* widget w is freed by soc-dapm.c */ in soc_tplg_remove_widget()
410 /* remove DAI configurations */
416 struct snd_soc_dai *dai, *_dai; in soc_tplg_remove_dai() local
421 if (dobj->unload) in soc_tplg_remove_dai()
422 dobj->unload(comp, dobj); in soc_tplg_remove_dai()
424 for_each_component_dais_safe(comp, dai, _dai) in soc_tplg_remove_dai()
425 if (dai->driver == dai_drv) in soc_tplg_remove_dai()
426 snd_soc_unregister_dai(dai); in soc_tplg_remove_dai()
428 list_del(&dobj->list); in soc_tplg_remove_dai()
431 /* remove link configurations */
435 struct snd_soc_dai_link *link = in soc_tplg_remove_link() local
441 if (dobj->unload) in soc_tplg_remove_link()
442 dobj->unload(comp, dobj); in soc_tplg_remove_link()
444 list_del(&dobj->list); in soc_tplg_remove_link()
445 snd_soc_remove_pcm_runtime(comp->card, in soc_tplg_remove_link()
446 snd_soc_get_pcm_runtime(comp->card, link)); in soc_tplg_remove_link()
449 /* unload dai link */
456 if (dobj->unload) in remove_backend_link()
457 dobj->unload(comp, dobj); in remove_backend_link()
460 * We don't free the link here as what soc_tplg_remove_link() do since BE in remove_backend_link()
464 dobj->type = SND_SOC_DOBJ_NONE; in remove_backend_link()
465 list_del(&dobj->list); in remove_backend_link()
477 if (le32_to_cpu(hdr->ops.info) == SND_SOC_TPLG_CTL_BYTES in soc_tplg_kcontrol_bind_io()
478 && k->iface & SNDRV_CTL_ELEM_IFACE_MIXER in soc_tplg_kcontrol_bind_io()
479 && (k->access & SNDRV_CTL_ELEM_ACCESS_TLV_READ in soc_tplg_kcontrol_bind_io()
480 || k->access & SNDRV_CTL_ELEM_ACCESS_TLV_WRITE) in soc_tplg_kcontrol_bind_io()
481 && k->access & SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK) { in soc_tplg_kcontrol_bind_io()
483 struct snd_soc_tplg_bytes_control *be; in soc_tplg_kcontrol_bind_io() local
485 sbe = (struct soc_bytes_ext *)k->private_value; in soc_tplg_kcontrol_bind_io()
486 be = container_of(hdr, struct snd_soc_tplg_bytes_control, hdr); in soc_tplg_kcontrol_bind_io()
491 k->info = snd_soc_bytes_info_ext; in soc_tplg_kcontrol_bind_io()
492 k->tlv.c = snd_soc_bytes_tlv_callback; in soc_tplg_kcontrol_bind_io()
495 * When a topology-based implementation abuses the in soc_tplg_kcontrol_bind_io()
499 * return an -EINVAL error and prevent the card from in soc_tplg_kcontrol_bind_io()
502 if (sbe->max > 512) in soc_tplg_kcontrol_bind_io()
503 k->access |= SNDRV_CTL_ELEM_ACCESS_SKIP_CHECK; in soc_tplg_kcontrol_bind_io()
505 ext_ops = tplg->bytes_ext_ops; in soc_tplg_kcontrol_bind_io()
506 num_ops = tplg->bytes_ext_ops_count; in soc_tplg_kcontrol_bind_io()
508 if (!sbe->put && in soc_tplg_kcontrol_bind_io()
509 ext_ops[i].id == le32_to_cpu(be->ext_ops.put)) in soc_tplg_kcontrol_bind_io()
510 sbe->put = ext_ops[i].put; in soc_tplg_kcontrol_bind_io()
511 if (!sbe->get && in soc_tplg_kcontrol_bind_io()
512 ext_ops[i].id == le32_to_cpu(be->ext_ops.get)) in soc_tplg_kcontrol_bind_io()
513 sbe->get = ext_ops[i].get; in soc_tplg_kcontrol_bind_io()
516 if ((k->access & SNDRV_CTL_ELEM_ACCESS_TLV_READ) && !sbe->get) in soc_tplg_kcontrol_bind_io()
517 return -EINVAL; in soc_tplg_kcontrol_bind_io()
518 if ((k->access & SNDRV_CTL_ELEM_ACCESS_TLV_WRITE) && !sbe->put) in soc_tplg_kcontrol_bind_io()
519 return -EINVAL; in soc_tplg_kcontrol_bind_io()
524 ops = tplg->io_ops; in soc_tplg_kcontrol_bind_io()
525 num_ops = tplg->io_ops_count; in soc_tplg_kcontrol_bind_io()
528 if (k->put == NULL && ops[i].id == le32_to_cpu(hdr->ops.put)) in soc_tplg_kcontrol_bind_io()
529 k->put = ops[i].put; in soc_tplg_kcontrol_bind_io()
530 if (k->get == NULL && ops[i].id == le32_to_cpu(hdr->ops.get)) in soc_tplg_kcontrol_bind_io()
531 k->get = ops[i].get; in soc_tplg_kcontrol_bind_io()
532 if (k->info == NULL && ops[i].id == le32_to_cpu(hdr->ops.info)) in soc_tplg_kcontrol_bind_io()
533 k->info = ops[i].info; in soc_tplg_kcontrol_bind_io()
537 if (k->put && k->get && k->info) in soc_tplg_kcontrol_bind_io()
545 if (k->put == NULL && ops[i].id == le32_to_cpu(hdr->ops.put)) in soc_tplg_kcontrol_bind_io()
546 k->put = ops[i].put; in soc_tplg_kcontrol_bind_io()
547 if (k->get == NULL && ops[i].id == le32_to_cpu(hdr->ops.get)) in soc_tplg_kcontrol_bind_io()
548 k->get = ops[i].get; in soc_tplg_kcontrol_bind_io()
549 if (k->info == NULL && ops[i].id == le32_to_cpu(hdr->ops.info)) in soc_tplg_kcontrol_bind_io()
550 k->info = ops[i].info; in soc_tplg_kcontrol_bind_io()
554 if (k->put && k->get && k->info) in soc_tplg_kcontrol_bind_io()
558 return -EINVAL; in soc_tplg_kcontrol_bind_io()
568 w->event = NULL; in snd_soc_tplg_widget_bind_event()
573 /* found - so assign event */ in snd_soc_tplg_widget_bind_event()
574 w->event = events[i].event_handler; in snd_soc_tplg_widget_bind_event()
580 return -EINVAL; in snd_soc_tplg_widget_bind_event()
590 if (tplg->ops && tplg->ops->control_load) in soc_tplg_control_load()
591 ret = tplg->ops->control_load(tplg->comp, tplg->index, k, hdr); in soc_tplg_control_load()
594 dev_err(tplg->dev, "ASoC: failed to init %s\n", hdr->name); in soc_tplg_control_load()
606 p = devm_kzalloc(tplg->dev, item_len + 2 * sizeof(unsigned int), GFP_KERNEL); in soc_tplg_create_tlv_db_scale()
608 return -ENOMEM; in soc_tplg_create_tlv_db_scale()
612 p[2] = le32_to_cpu(scale->min); in soc_tplg_create_tlv_db_scale()
613 p[3] = (le32_to_cpu(scale->step) & TLV_DB_SCALE_MASK) in soc_tplg_create_tlv_db_scale()
614 | (le32_to_cpu(scale->mute) ? TLV_DB_SCALE_MUTE : 0); in soc_tplg_create_tlv_db_scale()
616 kc->tlv.p = (void *)p; in soc_tplg_create_tlv_db_scale()
624 u32 access = le32_to_cpu(tc->access); in soc_tplg_create_tlv()
630 tplg_tlv = &tc->tlv; in soc_tplg_create_tlv()
631 switch (le32_to_cpu(tplg_tlv->type)) { in soc_tplg_create_tlv()
634 &tplg_tlv->scale); in soc_tplg_create_tlv()
638 dev_dbg(tplg->dev, "Unsupported TLV type %d\n", in soc_tplg_create_tlv()
639 tplg_tlv->type); in soc_tplg_create_tlv()
640 return -EINVAL; in soc_tplg_create_tlv()
649 struct snd_soc_tplg_bytes_control *be; in soc_tplg_dbytes_create() local
657 return -EINVAL; in soc_tplg_dbytes_create()
659 be = (struct snd_soc_tplg_bytes_control *)tplg->pos; in soc_tplg_dbytes_create()
662 if (strnlen(be->hdr.name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN) == in soc_tplg_dbytes_create()
664 return -EINVAL; in soc_tplg_dbytes_create()
666 sbe = devm_kzalloc(tplg->dev, sizeof(*sbe), GFP_KERNEL); in soc_tplg_dbytes_create()
668 return -ENOMEM; in soc_tplg_dbytes_create()
670 tplg->pos += (sizeof(struct snd_soc_tplg_bytes_control) + in soc_tplg_dbytes_create()
671 le32_to_cpu(be->priv.size)); in soc_tplg_dbytes_create()
673 dev_dbg(tplg->dev, in soc_tplg_dbytes_create()
675 be->hdr.name, be->hdr.access); in soc_tplg_dbytes_create()
678 kc.name = be->hdr.name; in soc_tplg_dbytes_create()
681 kc.access = le32_to_cpu(be->hdr.access); in soc_tplg_dbytes_create()
683 sbe->max = le32_to_cpu(be->max); in soc_tplg_dbytes_create()
684 sbe->dobj.type = SND_SOC_DOBJ_BYTES; in soc_tplg_dbytes_create()
685 if (tplg->ops) in soc_tplg_dbytes_create()
686 sbe->dobj.unload = tplg->ops->control_unload; in soc_tplg_dbytes_create()
687 INIT_LIST_HEAD(&sbe->dobj.list); in soc_tplg_dbytes_create()
690 ret = soc_tplg_kcontrol_bind_io(&be->hdr, &kc, tplg); in soc_tplg_dbytes_create()
692 soc_control_err(tplg, &be->hdr, be->hdr.name); in soc_tplg_dbytes_create()
697 ret = soc_tplg_control_load(tplg, &kc, &be->hdr); in soc_tplg_dbytes_create()
702 ret = soc_tplg_add_kcontrol(tplg, &kc, &sbe->dobj.control.kcontrol); in soc_tplg_dbytes_create()
706 list_add(&sbe->dobj.list, &tplg->comp->dobj_list); in soc_tplg_dbytes_create()
722 return -EINVAL; in soc_tplg_dmixer_create()
724 mc = (struct snd_soc_tplg_mixer_control *)tplg->pos; in soc_tplg_dmixer_create()
727 if (strnlen(mc->hdr.name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN) == in soc_tplg_dmixer_create()
729 return -EINVAL; in soc_tplg_dmixer_create()
731 sm = devm_kzalloc(tplg->dev, sizeof(*sm), GFP_KERNEL); in soc_tplg_dmixer_create()
733 return -ENOMEM; in soc_tplg_dmixer_create()
734 tplg->pos += (sizeof(struct snd_soc_tplg_mixer_control) + in soc_tplg_dmixer_create()
735 le32_to_cpu(mc->priv.size)); in soc_tplg_dmixer_create()
737 dev_dbg(tplg->dev, in soc_tplg_dmixer_create()
739 mc->hdr.name, mc->hdr.access); in soc_tplg_dmixer_create()
742 kc.name = mc->hdr.name; in soc_tplg_dmixer_create()
745 kc.access = le32_to_cpu(mc->hdr.access); in soc_tplg_dmixer_create()
748 sm->reg = tplg_chan_get_reg(tplg, mc->channel, SNDRV_CHMAP_FL); in soc_tplg_dmixer_create()
749 sm->rreg = tplg_chan_get_reg(tplg, mc->channel, SNDRV_CHMAP_FR); in soc_tplg_dmixer_create()
750 sm->shift = tplg_chan_get_shift(tplg, mc->channel, SNDRV_CHMAP_FL); in soc_tplg_dmixer_create()
751 sm->rshift = tplg_chan_get_shift(tplg, mc->channel, SNDRV_CHMAP_FR); in soc_tplg_dmixer_create()
753 sm->max = le32_to_cpu(mc->max); in soc_tplg_dmixer_create()
754 sm->min = le32_to_cpu(mc->min); in soc_tplg_dmixer_create()
755 sm->invert = le32_to_cpu(mc->invert); in soc_tplg_dmixer_create()
756 sm->platform_max = le32_to_cpu(mc->platform_max); in soc_tplg_dmixer_create()
757 sm->dobj.index = tplg->index; in soc_tplg_dmixer_create()
758 sm->dobj.type = SND_SOC_DOBJ_MIXER; in soc_tplg_dmixer_create()
759 if (tplg->ops) in soc_tplg_dmixer_create()
760 sm->dobj.unload = tplg->ops->control_unload; in soc_tplg_dmixer_create()
761 INIT_LIST_HEAD(&sm->dobj.list); in soc_tplg_dmixer_create()
764 ret = soc_tplg_kcontrol_bind_io(&mc->hdr, &kc, tplg); in soc_tplg_dmixer_create()
766 soc_control_err(tplg, &mc->hdr, mc->hdr.name); in soc_tplg_dmixer_create()
771 ret = soc_tplg_create_tlv(tplg, &kc, &mc->hdr); in soc_tplg_dmixer_create()
773 dev_err(tplg->dev, "ASoC: failed to create TLV %s\n", mc->hdr.name); in soc_tplg_dmixer_create()
778 ret = soc_tplg_control_load(tplg, &kc, &mc->hdr); in soc_tplg_dmixer_create()
783 ret = soc_tplg_add_kcontrol(tplg, &kc, &sm->dobj.control.kcontrol); in soc_tplg_dmixer_create()
787 list_add(&sm->dobj.list, &tplg->comp->dobj_list); in soc_tplg_dmixer_create()
798 if (le32_to_cpu(ec->items) > ARRAY_SIZE(ec->texts)) in soc_tplg_denum_create_texts()
799 return -EINVAL; in soc_tplg_denum_create_texts()
801 se->dobj.control.dtexts = in soc_tplg_denum_create_texts()
802 devm_kcalloc(tplg->dev, le32_to_cpu(ec->items), sizeof(char *), GFP_KERNEL); in soc_tplg_denum_create_texts()
803 if (se->dobj.control.dtexts == NULL) in soc_tplg_denum_create_texts()
804 return -ENOMEM; in soc_tplg_denum_create_texts()
806 for (i = 0; i < le32_to_cpu(ec->items); i++) { in soc_tplg_denum_create_texts()
808 if (strnlen(ec->texts[i], SNDRV_CTL_ELEM_ID_NAME_MAXLEN) == in soc_tplg_denum_create_texts()
810 ret = -EINVAL; in soc_tplg_denum_create_texts()
814 se->dobj.control.dtexts[i] = devm_kstrdup(tplg->dev, ec->texts[i], GFP_KERNEL); in soc_tplg_denum_create_texts()
815 if (!se->dobj.control.dtexts[i]) { in soc_tplg_denum_create_texts()
816 ret = -ENOMEM; in soc_tplg_denum_create_texts()
821 se->items = le32_to_cpu(ec->items); in soc_tplg_denum_create_texts()
822 se->texts = (const char * const *)se->dobj.control.dtexts; in soc_tplg_denum_create_texts()
836 * values instead of using ARRAY_SIZE(ec->values) due to the fact that in soc_tplg_denum_create_values()
838 * it is defined in UAPI header where it can't be easily changed. in soc_tplg_denum_create_values()
840 if (le32_to_cpu(ec->items) > SND_SOC_TPLG_NUM_TEXTS) in soc_tplg_denum_create_values()
841 return -EINVAL; in soc_tplg_denum_create_values()
843 se->dobj.control.dvalues = devm_kcalloc(tplg->dev, le32_to_cpu(ec->items), in soc_tplg_denum_create_values()
844 sizeof(*se->dobj.control.dvalues), in soc_tplg_denum_create_values()
846 if (!se->dobj.control.dvalues) in soc_tplg_denum_create_values()
847 return -ENOMEM; in soc_tplg_denum_create_values()
849 /* convert from little-endian */ in soc_tplg_denum_create_values()
850 for (i = 0; i < le32_to_cpu(ec->items); i++) { in soc_tplg_denum_create_values()
851 se->dobj.control.dvalues[i] = le32_to_cpu(ec->values[i]); in soc_tplg_denum_create_values()
854 se->items = le32_to_cpu(ec->items); in soc_tplg_denum_create_values()
855 se->values = (const unsigned int *)se->dobj.control.dvalues; in soc_tplg_denum_create_values()
869 return -EINVAL; in soc_tplg_denum_create()
871 ec = (struct snd_soc_tplg_enum_control *)tplg->pos; in soc_tplg_denum_create()
874 if (strnlen(ec->hdr.name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN) == in soc_tplg_denum_create()
876 return -EINVAL; in soc_tplg_denum_create()
878 se = devm_kzalloc(tplg->dev, (sizeof(*se)), GFP_KERNEL); in soc_tplg_denum_create()
880 return -ENOMEM; in soc_tplg_denum_create()
882 tplg->pos += (sizeof(struct snd_soc_tplg_enum_control) + in soc_tplg_denum_create()
883 le32_to_cpu(ec->priv.size)); in soc_tplg_denum_create()
885 dev_dbg(tplg->dev, "ASoC: adding enum kcontrol %s size %d\n", in soc_tplg_denum_create()
886 ec->hdr.name, ec->items); in soc_tplg_denum_create()
889 kc.name = ec->hdr.name; in soc_tplg_denum_create()
892 kc.access = le32_to_cpu(ec->hdr.access); in soc_tplg_denum_create()
894 se->reg = tplg_chan_get_reg(tplg, ec->channel, SNDRV_CHMAP_FL); in soc_tplg_denum_create()
895 se->shift_l = tplg_chan_get_shift(tplg, ec->channel, in soc_tplg_denum_create()
897 se->shift_r = tplg_chan_get_shift(tplg, ec->channel, in soc_tplg_denum_create()
900 se->mask = le32_to_cpu(ec->mask); in soc_tplg_denum_create()
901 se->dobj.index = tplg->index; in soc_tplg_denum_create()
902 se->dobj.type = SND_SOC_DOBJ_ENUM; in soc_tplg_denum_create()
903 if (tplg->ops) in soc_tplg_denum_create()
904 se->dobj.unload = tplg->ops->control_unload; in soc_tplg_denum_create()
905 INIT_LIST_HEAD(&se->dobj.list); in soc_tplg_denum_create()
907 switch (le32_to_cpu(ec->hdr.ops.info)) { in soc_tplg_denum_create()
912 dev_err(tplg->dev, in soc_tplg_denum_create()
914 ec->hdr.name); in soc_tplg_denum_create()
923 dev_err(tplg->dev, in soc_tplg_denum_create()
925 ec->hdr.name); in soc_tplg_denum_create()
930 ret = -EINVAL; in soc_tplg_denum_create()
931 dev_err(tplg->dev, in soc_tplg_denum_create()
933 ec->hdr.ops.info, ec->hdr.name); in soc_tplg_denum_create()
938 ret = soc_tplg_kcontrol_bind_io(&ec->hdr, &kc, tplg); in soc_tplg_denum_create()
940 soc_control_err(tplg, &ec->hdr, ec->hdr.name); in soc_tplg_denum_create()
945 ret = soc_tplg_control_load(tplg, &kc, &ec->hdr); in soc_tplg_denum_create()
950 ret = soc_tplg_add_kcontrol(tplg, &kc, &se->dobj.control.kcontrol); in soc_tplg_denum_create()
954 list_add(&se->dobj.list, &tplg->comp->dobj_list); in soc_tplg_denum_create()
966 dev_dbg(tplg->dev, "ASoC: adding %d kcontrols at 0x%lx\n", hdr->count, in soc_tplg_kcontrol_elems_load()
969 for (i = 0; i < le32_to_cpu(hdr->count); i++) { in soc_tplg_kcontrol_elems_load()
970 struct snd_soc_tplg_ctl_hdr *control_hdr = (struct snd_soc_tplg_ctl_hdr *)tplg->pos; in soc_tplg_kcontrol_elems_load()
972 if (le32_to_cpu(control_hdr->size) != sizeof(*control_hdr)) { in soc_tplg_kcontrol_elems_load()
973 dev_err(tplg->dev, "ASoC: invalid control size\n"); in soc_tplg_kcontrol_elems_load()
974 return -EINVAL; in soc_tplg_kcontrol_elems_load()
977 switch (le32_to_cpu(control_hdr->ops.info)) { in soc_tplg_kcontrol_elems_load()
985 ret = soc_tplg_dmixer_create(tplg, le32_to_cpu(hdr->payload_size)); in soc_tplg_kcontrol_elems_load()
992 ret = soc_tplg_denum_create(tplg, le32_to_cpu(hdr->payload_size)); in soc_tplg_kcontrol_elems_load()
995 ret = soc_tplg_dbytes_create(tplg, le32_to_cpu(hdr->payload_size)); in soc_tplg_kcontrol_elems_load()
999 return -EINVAL; in soc_tplg_kcontrol_elems_load()
1002 dev_err(tplg->dev, "ASoC: invalid control\n"); in soc_tplg_kcontrol_elems_load()
1015 if (tplg->ops && tplg->ops->dapm_route_load) in soc_tplg_add_route()
1016 return tplg->ops->dapm_route_load(tplg->comp, tplg->index, in soc_tplg_add_route()
1025 struct snd_soc_dapm_context *dapm = &tplg->comp->dapm; in soc_tplg_dapm_graph_elems_load()
1032 count = le32_to_cpu(hdr->count); in soc_tplg_dapm_graph_elems_load()
1036 count, le32_to_cpu(hdr->payload_size), "graph")) in soc_tplg_dapm_graph_elems_load()
1037 return -EINVAL; in soc_tplg_dapm_graph_elems_load()
1039 dev_dbg(tplg->dev, "ASoC: adding %d DAPM routes for index %d\n", count, in soc_tplg_dapm_graph_elems_load()
1040 hdr->index); in soc_tplg_dapm_graph_elems_load()
1043 route = devm_kzalloc(tplg->dev, sizeof(*route), GFP_KERNEL); in soc_tplg_dapm_graph_elems_load()
1045 return -ENOMEM; in soc_tplg_dapm_graph_elems_load()
1046 elem = (struct snd_soc_tplg_dapm_graph_elem *)tplg->pos; in soc_tplg_dapm_graph_elems_load()
1047 tplg->pos += sizeof(struct snd_soc_tplg_dapm_graph_elem); in soc_tplg_dapm_graph_elems_load()
1050 if ((strnlen(elem->source, maxlen) == maxlen) || in soc_tplg_dapm_graph_elems_load()
1051 (strnlen(elem->sink, maxlen) == maxlen) || in soc_tplg_dapm_graph_elems_load()
1052 (strnlen(elem->control, maxlen) == maxlen)) { in soc_tplg_dapm_graph_elems_load()
1053 ret = -EINVAL; in soc_tplg_dapm_graph_elems_load()
1057 route->source = devm_kstrdup(tplg->dev, elem->source, GFP_KERNEL); in soc_tplg_dapm_graph_elems_load()
1058 route->sink = devm_kstrdup(tplg->dev, elem->sink, GFP_KERNEL); in soc_tplg_dapm_graph_elems_load()
1059 if (!route->source || !route->sink) { in soc_tplg_dapm_graph_elems_load()
1060 ret = -ENOMEM; in soc_tplg_dapm_graph_elems_load()
1064 if (strnlen(elem->control, maxlen) != 0) { in soc_tplg_dapm_graph_elems_load()
1065 route->control = devm_kstrdup(tplg->dev, elem->control, GFP_KERNEL); in soc_tplg_dapm_graph_elems_load()
1066 if (!route->control) { in soc_tplg_dapm_graph_elems_load()
1067 ret = -ENOMEM; in soc_tplg_dapm_graph_elems_load()
1073 route->dobj.type = SND_SOC_DOBJ_GRAPH; in soc_tplg_dapm_graph_elems_load()
1074 if (tplg->ops) in soc_tplg_dapm_graph_elems_load()
1075 route->dobj.unload = tplg->ops->dapm_route_unload; in soc_tplg_dapm_graph_elems_load()
1076 route->dobj.index = tplg->index; in soc_tplg_dapm_graph_elems_load()
1077 list_add(&route->dobj.list, &tplg->comp->dobj_list); in soc_tplg_dapm_graph_elems_load()
1081 dev_err(tplg->dev, "ASoC: topology: add_route failed: %d\n", ret); in soc_tplg_dapm_graph_elems_load()
1098 mc = (struct snd_soc_tplg_mixer_control *)tplg->pos; in soc_tplg_dapm_widget_dmixer_create()
1101 if (strnlen(mc->hdr.name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN) == in soc_tplg_dapm_widget_dmixer_create()
1103 return -EINVAL; in soc_tplg_dapm_widget_dmixer_create()
1105 sm = devm_kzalloc(tplg->dev, sizeof(*sm), GFP_KERNEL); in soc_tplg_dapm_widget_dmixer_create()
1107 return -ENOMEM; in soc_tplg_dapm_widget_dmixer_create()
1109 tplg->pos += sizeof(struct snd_soc_tplg_mixer_control) + in soc_tplg_dapm_widget_dmixer_create()
1110 le32_to_cpu(mc->priv.size); in soc_tplg_dapm_widget_dmixer_create()
1112 dev_dbg(tplg->dev, " adding DAPM widget mixer control %s\n", in soc_tplg_dapm_widget_dmixer_create()
1113 mc->hdr.name); in soc_tplg_dapm_widget_dmixer_create()
1115 kc->private_value = (long)sm; in soc_tplg_dapm_widget_dmixer_create()
1116 kc->name = devm_kstrdup(tplg->dev, mc->hdr.name, GFP_KERNEL); in soc_tplg_dapm_widget_dmixer_create()
1117 if (!kc->name) in soc_tplg_dapm_widget_dmixer_create()
1118 return -ENOMEM; in soc_tplg_dapm_widget_dmixer_create()
1119 kc->iface = SNDRV_CTL_ELEM_IFACE_MIXER; in soc_tplg_dapm_widget_dmixer_create()
1120 kc->access = le32_to_cpu(mc->hdr.access); in soc_tplg_dapm_widget_dmixer_create()
1123 sm->reg = tplg_chan_get_reg(tplg, mc->channel, in soc_tplg_dapm_widget_dmixer_create()
1125 sm->rreg = tplg_chan_get_reg(tplg, mc->channel, in soc_tplg_dapm_widget_dmixer_create()
1127 sm->shift = tplg_chan_get_shift(tplg, mc->channel, in soc_tplg_dapm_widget_dmixer_create()
1129 sm->rshift = tplg_chan_get_shift(tplg, mc->channel, in soc_tplg_dapm_widget_dmixer_create()
1132 sm->max = le32_to_cpu(mc->max); in soc_tplg_dapm_widget_dmixer_create()
1133 sm->min = le32_to_cpu(mc->min); in soc_tplg_dapm_widget_dmixer_create()
1134 sm->invert = le32_to_cpu(mc->invert); in soc_tplg_dapm_widget_dmixer_create()
1135 sm->platform_max = le32_to_cpu(mc->platform_max); in soc_tplg_dapm_widget_dmixer_create()
1136 sm->dobj.index = tplg->index; in soc_tplg_dapm_widget_dmixer_create()
1137 INIT_LIST_HEAD(&sm->dobj.list); in soc_tplg_dapm_widget_dmixer_create()
1140 err = soc_tplg_kcontrol_bind_io(&mc->hdr, kc, tplg); in soc_tplg_dapm_widget_dmixer_create()
1142 soc_control_err(tplg, &mc->hdr, mc->hdr.name); in soc_tplg_dapm_widget_dmixer_create()
1147 err = soc_tplg_create_tlv(tplg, kc, &mc->hdr); in soc_tplg_dapm_widget_dmixer_create()
1149 dev_err(tplg->dev, "ASoC: failed to create TLV %s\n", in soc_tplg_dapm_widget_dmixer_create()
1150 mc->hdr.name); in soc_tplg_dapm_widget_dmixer_create()
1155 err = soc_tplg_control_load(tplg, kc, &mc->hdr); in soc_tplg_dapm_widget_dmixer_create()
1168 ec = (struct snd_soc_tplg_enum_control *)tplg->pos; in soc_tplg_dapm_widget_denum_create()
1170 if (strnlen(ec->hdr.name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN) == in soc_tplg_dapm_widget_denum_create()
1172 return -EINVAL; in soc_tplg_dapm_widget_denum_create()
1174 se = devm_kzalloc(tplg->dev, sizeof(*se), GFP_KERNEL); in soc_tplg_dapm_widget_denum_create()
1176 return -ENOMEM; in soc_tplg_dapm_widget_denum_create()
1178 tplg->pos += (sizeof(struct snd_soc_tplg_enum_control) + in soc_tplg_dapm_widget_denum_create()
1179 le32_to_cpu(ec->priv.size)); in soc_tplg_dapm_widget_denum_create()
1181 dev_dbg(tplg->dev, " adding DAPM widget enum control %s\n", in soc_tplg_dapm_widget_denum_create()
1182 ec->hdr.name); in soc_tplg_dapm_widget_denum_create()
1184 kc->private_value = (long)se; in soc_tplg_dapm_widget_denum_create()
1185 kc->name = devm_kstrdup(tplg->dev, ec->hdr.name, GFP_KERNEL); in soc_tplg_dapm_widget_denum_create()
1186 if (!kc->name) in soc_tplg_dapm_widget_denum_create()
1187 return -ENOMEM; in soc_tplg_dapm_widget_denum_create()
1188 kc->iface = SNDRV_CTL_ELEM_IFACE_MIXER; in soc_tplg_dapm_widget_denum_create()
1189 kc->access = le32_to_cpu(ec->hdr.access); in soc_tplg_dapm_widget_denum_create()
1192 se->reg = tplg_chan_get_reg(tplg, ec->channel, SNDRV_CHMAP_FL); in soc_tplg_dapm_widget_denum_create()
1193 se->shift_l = tplg_chan_get_shift(tplg, ec->channel, in soc_tplg_dapm_widget_denum_create()
1195 se->shift_r = tplg_chan_get_shift(tplg, ec->channel, in soc_tplg_dapm_widget_denum_create()
1198 se->items = le32_to_cpu(ec->items); in soc_tplg_dapm_widget_denum_create()
1199 se->mask = le32_to_cpu(ec->mask); in soc_tplg_dapm_widget_denum_create()
1200 se->dobj.index = tplg->index; in soc_tplg_dapm_widget_denum_create()
1202 switch (le32_to_cpu(ec->hdr.ops.info)) { in soc_tplg_dapm_widget_denum_create()
1207 dev_err(tplg->dev, "ASoC: could not create values for %s\n", in soc_tplg_dapm_widget_denum_create()
1208 ec->hdr.name); in soc_tplg_dapm_widget_denum_create()
1217 dev_err(tplg->dev, "ASoC: could not create texts for %s\n", in soc_tplg_dapm_widget_denum_create()
1218 ec->hdr.name); in soc_tplg_dapm_widget_denum_create()
1223 dev_err(tplg->dev, "ASoC: invalid enum control type %d for %s\n", in soc_tplg_dapm_widget_denum_create()
1224 ec->hdr.ops.info, ec->hdr.name); in soc_tplg_dapm_widget_denum_create()
1225 return -EINVAL; in soc_tplg_dapm_widget_denum_create()
1229 err = soc_tplg_kcontrol_bind_io(&ec->hdr, kc, tplg); in soc_tplg_dapm_widget_denum_create()
1231 soc_control_err(tplg, &ec->hdr, ec->hdr.name); in soc_tplg_dapm_widget_denum_create()
1236 err = soc_tplg_control_load(tplg, kc, &ec->hdr); in soc_tplg_dapm_widget_denum_create()
1245 struct snd_soc_tplg_bytes_control *be; in soc_tplg_dapm_widget_dbytes_create() local
1249 be = (struct snd_soc_tplg_bytes_control *)tplg->pos; in soc_tplg_dapm_widget_dbytes_create()
1252 if (strnlen(be->hdr.name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN) == in soc_tplg_dapm_widget_dbytes_create()
1254 return -EINVAL; in soc_tplg_dapm_widget_dbytes_create()
1256 sbe = devm_kzalloc(tplg->dev, sizeof(*sbe), GFP_KERNEL); in soc_tplg_dapm_widget_dbytes_create()
1258 return -ENOMEM; in soc_tplg_dapm_widget_dbytes_create()
1260 tplg->pos += (sizeof(struct snd_soc_tplg_bytes_control) + in soc_tplg_dapm_widget_dbytes_create()
1261 le32_to_cpu(be->priv.size)); in soc_tplg_dapm_widget_dbytes_create()
1263 dev_dbg(tplg->dev, in soc_tplg_dapm_widget_dbytes_create()
1265 be->hdr.name, be->hdr.access); in soc_tplg_dapm_widget_dbytes_create()
1267 kc->private_value = (long)sbe; in soc_tplg_dapm_widget_dbytes_create()
1268 kc->name = devm_kstrdup(tplg->dev, be->hdr.name, GFP_KERNEL); in soc_tplg_dapm_widget_dbytes_create()
1269 if (!kc->name) in soc_tplg_dapm_widget_dbytes_create()
1270 return -ENOMEM; in soc_tplg_dapm_widget_dbytes_create()
1271 kc->iface = SNDRV_CTL_ELEM_IFACE_MIXER; in soc_tplg_dapm_widget_dbytes_create()
1272 kc->access = le32_to_cpu(be->hdr.access); in soc_tplg_dapm_widget_dbytes_create()
1274 sbe->max = le32_to_cpu(be->max); in soc_tplg_dapm_widget_dbytes_create()
1275 INIT_LIST_HEAD(&sbe->dobj.list); in soc_tplg_dapm_widget_dbytes_create()
1278 err = soc_tplg_kcontrol_bind_io(&be->hdr, kc, tplg); in soc_tplg_dapm_widget_dbytes_create()
1280 soc_control_err(tplg, &be->hdr, be->hdr.name); in soc_tplg_dapm_widget_dbytes_create()
1285 err = soc_tplg_control_load(tplg, kc, &be->hdr); in soc_tplg_dapm_widget_dbytes_create()
1295 struct snd_soc_dapm_context *dapm = &tplg->comp->dapm; in soc_tplg_dapm_widget_create()
1298 struct snd_soc_card *card = tplg->comp->card; in soc_tplg_dapm_widget_create()
1307 if (strnlen(w->name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN) == in soc_tplg_dapm_widget_create()
1309 return -EINVAL; in soc_tplg_dapm_widget_create()
1310 if (strnlen(w->sname, SNDRV_CTL_ELEM_ID_NAME_MAXLEN) == in soc_tplg_dapm_widget_create()
1312 return -EINVAL; in soc_tplg_dapm_widget_create()
1314 dev_dbg(tplg->dev, "ASoC: creating DAPM widget %s id %d\n", in soc_tplg_dapm_widget_create()
1315 w->name, w->id); in soc_tplg_dapm_widget_create()
1320 template.id = get_widget_id(le32_to_cpu(w->id)); in soc_tplg_dapm_widget_create()
1325 template.name = kstrdup(w->name, GFP_KERNEL); in soc_tplg_dapm_widget_create()
1327 return -ENOMEM; in soc_tplg_dapm_widget_create()
1328 template.sname = kstrdup(w->sname, GFP_KERNEL); in soc_tplg_dapm_widget_create()
1330 ret = -ENOMEM; in soc_tplg_dapm_widget_create()
1333 template.reg = le32_to_cpu(w->reg); in soc_tplg_dapm_widget_create()
1334 template.shift = le32_to_cpu(w->shift); in soc_tplg_dapm_widget_create()
1335 template.mask = le32_to_cpu(w->mask); in soc_tplg_dapm_widget_create()
1336 template.subseq = le32_to_cpu(w->subseq); in soc_tplg_dapm_widget_create()
1337 template.on_val = w->invert ? 0 : 1; in soc_tplg_dapm_widget_create()
1338 template.off_val = w->invert ? 1 : 0; in soc_tplg_dapm_widget_create()
1339 template.ignore_suspend = le32_to_cpu(w->ignore_suspend); in soc_tplg_dapm_widget_create()
1340 template.event_flags = le16_to_cpu(w->event_flags); in soc_tplg_dapm_widget_create()
1341 template.dobj.index = tplg->index; in soc_tplg_dapm_widget_create()
1343 tplg->pos += in soc_tplg_dapm_widget_create()
1345 le32_to_cpu(w->priv.size)); in soc_tplg_dapm_widget_create()
1347 if (w->num_kcontrols == 0) { in soc_tplg_dapm_widget_create()
1352 template.num_kcontrols = le32_to_cpu(w->num_kcontrols); in soc_tplg_dapm_widget_create()
1353 kc = devm_kcalloc(tplg->dev, le32_to_cpu(w->num_kcontrols), sizeof(*kc), GFP_KERNEL); in soc_tplg_dapm_widget_create()
1355 ret = -ENOMEM; in soc_tplg_dapm_widget_create()
1359 kcontrol_type = devm_kcalloc(tplg->dev, le32_to_cpu(w->num_kcontrols), sizeof(unsigned int), in soc_tplg_dapm_widget_create()
1362 ret = -ENOMEM; in soc_tplg_dapm_widget_create()
1366 for (i = 0; i < le32_to_cpu(w->num_kcontrols); i++) { in soc_tplg_dapm_widget_create()
1367 control_hdr = (struct snd_soc_tplg_ctl_hdr *)tplg->pos; in soc_tplg_dapm_widget_create()
1368 switch (le32_to_cpu(control_hdr->ops.info)) { in soc_tplg_dapm_widget_create()
1406 dev_err(tplg->dev, "ASoC: invalid widget control type %d:%d:%d\n", in soc_tplg_dapm_widget_create()
1407 control_hdr->ops.get, control_hdr->ops.put, in soc_tplg_dapm_widget_create()
1408 le32_to_cpu(control_hdr->ops.info)); in soc_tplg_dapm_widget_create()
1409 ret = -EINVAL; in soc_tplg_dapm_widget_create()
1415 dev_dbg(tplg->dev, "ASoC: template %s with %d/%d/%d (mixer/enum/bytes) control\n", in soc_tplg_dapm_widget_create()
1416 w->name, mixer_count, enum_count, bytes_count); in soc_tplg_dapm_widget_create()
1434 widget->dobj.type = SND_SOC_DOBJ_WIDGET; in soc_tplg_dapm_widget_create()
1435 widget->dobj.widget.kcontrol_type = kcontrol_type; in soc_tplg_dapm_widget_create()
1436 if (tplg->ops) in soc_tplg_dapm_widget_create()
1437 widget->dobj.unload = tplg->ops->widget_unload; in soc_tplg_dapm_widget_create()
1438 widget->dobj.index = tplg->index; in soc_tplg_dapm_widget_create()
1439 list_add(&widget->dobj.list, &tplg->comp->dobj_list); in soc_tplg_dapm_widget_create()
1451 soc_tplg_remove_widget(widget->dapm->component, &widget->dobj, SOC_TPLG_PASS_WIDGET); in soc_tplg_dapm_widget_create()
1465 count = le32_to_cpu(hdr->count); in soc_tplg_dapm_widget_elems_load()
1467 dev_dbg(tplg->dev, "ASoC: adding %d DAPM widgets\n", count); in soc_tplg_dapm_widget_elems_load()
1470 struct snd_soc_tplg_dapm_widget *widget = (struct snd_soc_tplg_dapm_widget *) tplg->pos; in soc_tplg_dapm_widget_elems_load()
1475 * use sizeof instead of widget->size, as we can't be sure in soc_tplg_dapm_widget_elems_load()
1478 if (soc_tplg_get_offset(tplg) + sizeof(*widget) >= tplg->fw->size) { in soc_tplg_dapm_widget_elems_load()
1479 dev_err(tplg->dev, "ASoC: invalid widget data size\n"); in soc_tplg_dapm_widget_elems_load()
1480 return -EINVAL; in soc_tplg_dapm_widget_elems_load()
1484 if (le32_to_cpu(widget->size) != sizeof(*widget)) { in soc_tplg_dapm_widget_elems_load()
1485 dev_err(tplg->dev, "ASoC: invalid widget size\n"); in soc_tplg_dapm_widget_elems_load()
1486 return -EINVAL; in soc_tplg_dapm_widget_elems_load()
1490 if (soc_tplg_get_offset(tplg) + le32_to_cpu(widget->priv.size) >= tplg->fw->size) { in soc_tplg_dapm_widget_elems_load()
1491 dev_err(tplg->dev, "ASoC: invalid widget private data size\n"); in soc_tplg_dapm_widget_elems_load()
1492 return -EINVAL; in soc_tplg_dapm_widget_elems_load()
1497 dev_err(tplg->dev, "ASoC: failed to load widget %s\n", in soc_tplg_dapm_widget_elems_load()
1498 widget->name); in soc_tplg_dapm_widget_elems_load()
1508 struct snd_soc_card *card = tplg->comp->card; in soc_tplg_dapm_complete()
1515 dev_warn(tplg->dev, "ASoC: Parent card not yet available, widget card binding deferred\n"); in soc_tplg_dapm_complete()
1521 dev_err(tplg->dev, "ASoC: failed to create new widgets %d\n", ret); in soc_tplg_dapm_complete()
1529 stream->stream_name = devm_kstrdup(tplg->dev, caps->name, GFP_KERNEL); in set_stream_info()
1530 if (!stream->stream_name) in set_stream_info()
1531 return -ENOMEM; in set_stream_info()
1533 stream->channels_min = le32_to_cpu(caps->channels_min); in set_stream_info()
1534 stream->channels_max = le32_to_cpu(caps->channels_max); in set_stream_info()
1535 stream->rates = le32_to_cpu(caps->rates); in set_stream_info()
1536 stream->rate_min = le32_to_cpu(caps->rate_min); in set_stream_info()
1537 stream->rate_max = le32_to_cpu(caps->rate_max); in set_stream_info()
1538 stream->formats = le64_to_cpu(caps->formats); in set_stream_info()
1539 stream->sig_bits = le32_to_cpu(caps->sig_bits); in set_stream_info()
1548 dai_drv->symmetric_rate = in set_dai_flags()
1552 dai_drv->symmetric_channels = in set_dai_flags()
1557 dai_drv->symmetric_sample_bits = in set_dai_flags()
1572 struct snd_soc_dai *dai; in soc_tplg_dai_create() local
1574 snd_soc_component_get_dapm(tplg->comp); in soc_tplg_dai_create()
1577 dai_drv = devm_kzalloc(tplg->dev, sizeof(struct snd_soc_dai_driver), GFP_KERNEL); in soc_tplg_dai_create()
1579 return -ENOMEM; in soc_tplg_dai_create()
1581 if (strlen(pcm->dai_name)) { in soc_tplg_dai_create()
1582 dai_drv->name = devm_kstrdup(tplg->dev, pcm->dai_name, GFP_KERNEL); in soc_tplg_dai_create()
1583 if (!dai_drv->name) { in soc_tplg_dai_create()
1584 ret = -ENOMEM; in soc_tplg_dai_create()
1588 dai_drv->id = le32_to_cpu(pcm->dai_id); in soc_tplg_dai_create()
1590 if (pcm->playback) { in soc_tplg_dai_create()
1591 stream = &dai_drv->playback; in soc_tplg_dai_create()
1592 caps = &pcm->caps[SND_SOC_TPLG_STREAM_PLAYBACK]; in soc_tplg_dai_create()
1598 if (pcm->capture) { in soc_tplg_dai_create()
1599 stream = &dai_drv->capture; in soc_tplg_dai_create()
1600 caps = &pcm->caps[SND_SOC_TPLG_STREAM_CAPTURE]; in soc_tplg_dai_create()
1606 if (pcm->compress) in soc_tplg_dai_create()
1607 dai_drv->ops = &tplg_dai_ops; in soc_tplg_dai_create()
1612 dev_err(tplg->dev, "ASoC: DAI loading failed\n"); in soc_tplg_dai_create()
1616 dai_drv->dobj.index = tplg->index; in soc_tplg_dai_create()
1617 dai_drv->dobj.type = SND_SOC_DOBJ_PCM; in soc_tplg_dai_create()
1618 if (tplg->ops) in soc_tplg_dai_create()
1619 dai_drv->dobj.unload = tplg->ops->dai_unload; in soc_tplg_dai_create()
1620 list_add(&dai_drv->dobj.list, &tplg->comp->dobj_list); in soc_tplg_dai_create()
1622 /* register the DAI to the component */ in soc_tplg_dai_create()
1623 dai = snd_soc_register_dai(tplg->comp, dai_drv, false); in soc_tplg_dai_create()
1624 if (!dai) in soc_tplg_dai_create()
1625 return -ENOMEM; in soc_tplg_dai_create()
1627 /* Create the DAI widgets here */ in soc_tplg_dai_create()
1628 ret = snd_soc_dapm_new_dai_widgets(dapm, dai); in soc_tplg_dai_create()
1630 dev_err(dai->dev, "Failed to create DAI widgets %d\n", ret); in soc_tplg_dai_create()
1631 snd_soc_unregister_dai(dai); in soc_tplg_dai_create()
1641 static void set_link_flags(struct snd_soc_dai_link *link, in set_link_flags() argument
1645 link->symmetric_rate = in set_link_flags()
1649 link->symmetric_channels = in set_link_flags()
1654 link->symmetric_sample_bits = in set_link_flags()
1659 link->ignore_suspend = in set_link_flags()
1664 /* create the FE DAI link */
1668 struct snd_soc_dai_link *link; in soc_tplg_fe_link_create() local
1672 /* link + cpu + codec + platform */ in soc_tplg_fe_link_create()
1673 link = devm_kzalloc(tplg->dev, sizeof(*link) + (3 * sizeof(*dlc)), GFP_KERNEL); in soc_tplg_fe_link_create()
1674 if (link == NULL) in soc_tplg_fe_link_create()
1675 return -ENOMEM; in soc_tplg_fe_link_create()
1677 dlc = (struct snd_soc_dai_link_component *)(link + 1); in soc_tplg_fe_link_create()
1679 link->cpus = &dlc[0]; in soc_tplg_fe_link_create()
1680 link->num_cpus = 1; in soc_tplg_fe_link_create()
1682 link->dobj.index = tplg->index; in soc_tplg_fe_link_create()
1683 link->dobj.type = SND_SOC_DOBJ_DAI_LINK; in soc_tplg_fe_link_create()
1684 if (tplg->ops) in soc_tplg_fe_link_create()
1685 link->dobj.unload = tplg->ops->link_unload; in soc_tplg_fe_link_create()
1687 if (strlen(pcm->pcm_name)) { in soc_tplg_fe_link_create()
1688 link->name = devm_kstrdup(tplg->dev, pcm->pcm_name, GFP_KERNEL); in soc_tplg_fe_link_create()
1689 link->stream_name = devm_kstrdup(tplg->dev, pcm->pcm_name, GFP_KERNEL); in soc_tplg_fe_link_create()
1690 if (!link->name || !link->stream_name) { in soc_tplg_fe_link_create()
1691 ret = -ENOMEM; in soc_tplg_fe_link_create()
1695 link->id = le32_to_cpu(pcm->pcm_id); in soc_tplg_fe_link_create()
1697 if (strlen(pcm->dai_name)) { in soc_tplg_fe_link_create()
1698 link->cpus->dai_name = devm_kstrdup(tplg->dev, pcm->dai_name, GFP_KERNEL); in soc_tplg_fe_link_create()
1699 if (!link->cpus->dai_name) { in soc_tplg_fe_link_create()
1700 ret = -ENOMEM; in soc_tplg_fe_link_create()
1706 * Many topology are assuming link has Codec / Platform, and in soc_tplg_fe_link_create()
1707 * these might be overwritten at soc_tplg_dai_link_load(). in soc_tplg_fe_link_create()
1710 link->codecs = &dlc[1]; /* Don't use &asoc_dummy_dlc here */ in soc_tplg_fe_link_create()
1711 link->codecs->name = "snd-soc-dummy"; in soc_tplg_fe_link_create()
1712 link->codecs->dai_name = "snd-soc-dummy-dai"; in soc_tplg_fe_link_create()
1713 link->num_codecs = 1; in soc_tplg_fe_link_create()
1715 link->platforms = &dlc[2]; /* Don't use &asoc_dummy_dlc here */ in soc_tplg_fe_link_create()
1716 link->platforms->name = "snd-soc-dummy"; in soc_tplg_fe_link_create()
1717 link->num_platforms = 1; in soc_tplg_fe_link_create()
1720 link->dynamic = 1; in soc_tplg_fe_link_create()
1721 link->ignore_pmdown_time = 1; in soc_tplg_fe_link_create()
1722 link->dpcm_playback = le32_to_cpu(pcm->playback); in soc_tplg_fe_link_create()
1723 link->dpcm_capture = le32_to_cpu(pcm->capture); in soc_tplg_fe_link_create()
1724 if (pcm->flag_mask) in soc_tplg_fe_link_create()
1725 set_link_flags(link, in soc_tplg_fe_link_create()
1726 le32_to_cpu(pcm->flag_mask), in soc_tplg_fe_link_create()
1727 le32_to_cpu(pcm->flags)); in soc_tplg_fe_link_create()
1730 ret = soc_tplg_dai_link_load(tplg, link, NULL); in soc_tplg_fe_link_create()
1732 dev_err(tplg->dev, "ASoC: FE link loading failed\n"); in soc_tplg_fe_link_create()
1736 ret = snd_soc_add_pcm_runtimes(tplg->comp->card, link, 1); in soc_tplg_fe_link_create()
1738 if (ret != -EPROBE_DEFER) in soc_tplg_fe_link_create()
1739 dev_err(tplg->dev, "ASoC: adding FE link failed\n"); in soc_tplg_fe_link_create()
1743 list_add(&link->dobj.list, &tplg->comp->dobj_list); in soc_tplg_fe_link_create()
1750 /* create a FE DAI and DAI link from the PCM object */
1767 dest->size = cpu_to_le32(sizeof(*dest)); in stream_caps_new_ver()
1768 memcpy(dest->name, src->name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN); in stream_caps_new_ver()
1769 dest->formats = src->formats; in stream_caps_new_ver()
1770 dest->rates = src->rates; in stream_caps_new_ver()
1771 dest->rate_min = src->rate_min; in stream_caps_new_ver()
1772 dest->rate_max = src->rate_max; in stream_caps_new_ver()
1773 dest->channels_min = src->channels_min; in stream_caps_new_ver()
1774 dest->channels_max = src->channels_max; in stream_caps_new_ver()
1775 dest->periods_min = src->periods_min; in stream_caps_new_ver()
1776 dest->periods_max = src->periods_max; in stream_caps_new_ver()
1777 dest->period_size_min = src->period_size_min; in stream_caps_new_ver()
1778 dest->period_size_max = src->period_size_max; in stream_caps_new_ver()
1779 dest->buffer_size_min = src->buffer_size_min; in stream_caps_new_ver()
1780 dest->buffer_size_max = src->buffer_size_max; in stream_caps_new_ver()
1784 * pcm_new_ver - Create the new version of PCM from the old version.
1801 if (le32_to_cpu(src->size) != sizeof(*src_v4)) { in pcm_new_ver()
1802 dev_err(tplg->dev, "ASoC: invalid PCM size\n"); in pcm_new_ver()
1803 return -EINVAL; in pcm_new_ver()
1806 dev_warn(tplg->dev, "ASoC: old version of PCM\n"); in pcm_new_ver()
1810 return -ENOMEM; in pcm_new_ver()
1812 dest->size = cpu_to_le32(sizeof(*dest)); /* size of latest abi version */ in pcm_new_ver()
1813 memcpy(dest->pcm_name, src_v4->pcm_name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN); in pcm_new_ver()
1814 memcpy(dest->dai_name, src_v4->dai_name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN); in pcm_new_ver()
1815 dest->pcm_id = src_v4->pcm_id; in pcm_new_ver()
1816 dest->dai_id = src_v4->dai_id; in pcm_new_ver()
1817 dest->playback = src_v4->playback; in pcm_new_ver()
1818 dest->capture = src_v4->capture; in pcm_new_ver()
1819 dest->compress = src_v4->compress; in pcm_new_ver()
1820 dest->num_streams = src_v4->num_streams; in pcm_new_ver()
1821 for (i = 0; i < le32_to_cpu(dest->num_streams); i++) in pcm_new_ver()
1822 memcpy(&dest->stream[i], &src_v4->stream[i], in pcm_new_ver()
1826 stream_caps_new_ver(&dest->caps[i], &src_v4->caps[i]); in pcm_new_ver()
1842 count = le32_to_cpu(hdr->count); in soc_tplg_pcm_elems_load()
1845 pcm = (struct snd_soc_tplg_pcm *)tplg->pos; in soc_tplg_pcm_elems_load()
1846 size = le32_to_cpu(pcm->size); in soc_tplg_pcm_elems_load()
1849 dev_err(tplg->dev, "ASoC: invalid size %d for PCM elems\n", in soc_tplg_pcm_elems_load()
1851 return -EINVAL; in soc_tplg_pcm_elems_load()
1856 le32_to_cpu(hdr->payload_size), in soc_tplg_pcm_elems_load()
1857 "PCM DAI")) in soc_tplg_pcm_elems_load()
1858 return -EINVAL; in soc_tplg_pcm_elems_load()
1861 pcm = (struct snd_soc_tplg_pcm *)tplg->pos; in soc_tplg_pcm_elems_load()
1862 size = le32_to_cpu(pcm->size); in soc_tplg_pcm_elems_load()
1877 /* create the FE DAIs and DAI links */ in soc_tplg_pcm_elems_load()
1885 /* offset by version-specific struct size and in soc_tplg_pcm_elems_load()
1888 tplg->pos += size + le32_to_cpu(_pcm->priv.size); in soc_tplg_pcm_elems_load()
1894 dev_dbg(tplg->dev, "ASoC: adding %d PCM DAIs\n", count); in soc_tplg_pcm_elems_load()
1900 * set_link_hw_format - Set the HW audio format of the physical DAI link.
1901 * @link: &snd_soc_dai_link which should be updated
1902 * @cfg: physical link configs.
1905 * a default format ID for the physical link. This function will use this
1906 * default ID to choose the HW format to set the link's DAI format for init.
1908 static void set_link_hw_format(struct snd_soc_dai_link *link, in set_link_hw_format() argument
1916 for (i = 0; i < le32_to_cpu(cfg->num_hw_configs); i++) { in set_link_hw_format()
1917 hw_config = &cfg->hw_config[i]; in set_link_hw_format()
1918 if (hw_config->id != cfg->default_hw_config_id) in set_link_hw_format()
1921 link->dai_fmt = le32_to_cpu(hw_config->fmt) & in set_link_hw_format()
1925 switch (hw_config->clock_gated) { in set_link_hw_format()
1927 link->dai_fmt |= SND_SOC_DAIFMT_GATED; in set_link_hw_format()
1931 link->dai_fmt |= SND_SOC_DAIFMT_CONT; in set_link_hw_format()
1940 invert_bclk = hw_config->invert_bclk; in set_link_hw_format()
1941 invert_fsync = hw_config->invert_fsync; in set_link_hw_format()
1943 link->dai_fmt |= SND_SOC_DAIFMT_NB_NF; in set_link_hw_format()
1945 link->dai_fmt |= SND_SOC_DAIFMT_NB_IF; in set_link_hw_format()
1947 link->dai_fmt |= SND_SOC_DAIFMT_IB_NF; in set_link_hw_format()
1949 link->dai_fmt |= SND_SOC_DAIFMT_IB_IF; in set_link_hw_format()
1952 bclk_provider = (hw_config->bclk_provider == in set_link_hw_format()
1954 fsync_provider = (hw_config->fsync_provider == in set_link_hw_format()
1957 link->dai_fmt |= SND_SOC_DAIFMT_CBP_CFP; in set_link_hw_format()
1959 link->dai_fmt |= SND_SOC_DAIFMT_CBC_CFP; in set_link_hw_format()
1961 link->dai_fmt |= SND_SOC_DAIFMT_CBP_CFC; in set_link_hw_format()
1963 link->dai_fmt |= SND_SOC_DAIFMT_CBC_CFC; in set_link_hw_format()
1968 * link_new_ver - Create a new physical link config from the old
1971 * @src: old version of phyical link config as a source
1972 * @link: latest version of physical link config created from the source
1974 * Support from version 4. User need free the returned link config manually.
1978 struct snd_soc_tplg_link_config **link) in link_new_ver() argument
1984 *link = NULL; in link_new_ver()
1986 if (le32_to_cpu(src->size) != in link_new_ver()
1988 dev_err(tplg->dev, "ASoC: invalid physical link config size\n"); in link_new_ver()
1989 return -EINVAL; in link_new_ver()
1992 dev_warn(tplg->dev, "ASoC: old version of physical link config\n"); in link_new_ver()
1997 return -ENOMEM; in link_new_ver()
1999 dest->size = cpu_to_le32(sizeof(*dest)); in link_new_ver()
2000 dest->id = src_v4->id; in link_new_ver()
2001 dest->num_streams = src_v4->num_streams; in link_new_ver()
2002 for (i = 0; i < le32_to_cpu(dest->num_streams); i++) in link_new_ver()
2003 memcpy(&dest->stream[i], &src_v4->stream[i], in link_new_ver()
2006 *link = dest; in link_new_ver()
2011 * snd_soc_find_dai_link - Find a DAI link
2014 * @id: DAI link ID to match
2015 * @name: DAI link name to match, optional
2016 * @stream_name: DAI link stream name to match, optional
2018 * This function will search all existing DAI links of the soc card to
2019 * find the link of the same ID. Since DAI links may not have their
2023 * Return: pointer of DAI link, or NULL if not found.
2032 struct snd_soc_dai_link *link = rtd->dai_link; in snd_soc_find_dai_link() local
2034 if (link->id != id) in snd_soc_find_dai_link()
2037 if (name && (!link->name || !strstr(link->name, name))) in snd_soc_find_dai_link()
2040 if (stream_name && (!link->stream_name || in snd_soc_find_dai_link()
2041 !strstr(link->stream_name, stream_name))) in snd_soc_find_dai_link()
2044 return link; in snd_soc_find_dai_link()
2050 /* Find and configure an existing physical DAI link */
2054 struct snd_soc_dai_link *link; in soc_tplg_link_config() local
2059 len = strnlen(cfg->name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN); in soc_tplg_link_config()
2061 return -EINVAL; in soc_tplg_link_config()
2063 name = cfg->name; in soc_tplg_link_config()
2067 len = strnlen(cfg->stream_name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN); in soc_tplg_link_config()
2069 return -EINVAL; in soc_tplg_link_config()
2071 stream_name = cfg->stream_name; in soc_tplg_link_config()
2075 link = snd_soc_find_dai_link(tplg->comp->card, le32_to_cpu(cfg->id), in soc_tplg_link_config()
2077 if (!link) { in soc_tplg_link_config()
2078 dev_err(tplg->dev, "ASoC: physical link %s (id %d) not exist\n", in soc_tplg_link_config()
2079 name, cfg->id); in soc_tplg_link_config()
2080 return -EINVAL; in soc_tplg_link_config()
2084 if (cfg->num_hw_configs) in soc_tplg_link_config()
2085 set_link_hw_format(link, cfg); in soc_tplg_link_config()
2088 if (cfg->flag_mask) in soc_tplg_link_config()
2089 set_link_flags(link, in soc_tplg_link_config()
2090 le32_to_cpu(cfg->flag_mask), in soc_tplg_link_config()
2091 le32_to_cpu(cfg->flags)); in soc_tplg_link_config()
2094 ret = soc_tplg_dai_link_load(tplg, link, cfg); in soc_tplg_link_config()
2096 dev_err(tplg->dev, "ASoC: physical link loading failed\n"); in soc_tplg_link_config()
2101 link->dobj.index = tplg->index; in soc_tplg_link_config()
2102 link->dobj.type = SND_SOC_DOBJ_BACKEND_LINK; in soc_tplg_link_config()
2103 if (tplg->ops) in soc_tplg_link_config()
2104 link->dobj.unload = tplg->ops->link_unload; in soc_tplg_link_config()
2105 list_add(&link->dobj.list, &tplg->comp->dobj_list); in soc_tplg_link_config()
2111 /* Load physical link config elements from the topology context */
2115 struct snd_soc_tplg_link_config *link, *_link; in soc_tplg_link_elems_load() local
2121 count = le32_to_cpu(hdr->count); in soc_tplg_link_elems_load()
2124 link = (struct snd_soc_tplg_link_config *)tplg->pos; in soc_tplg_link_elems_load()
2125 size = le32_to_cpu(link->size); in soc_tplg_link_elems_load()
2128 dev_err(tplg->dev, "ASoC: invalid size %d for physical link elems\n", in soc_tplg_link_elems_load()
2130 return -EINVAL; in soc_tplg_link_elems_load()
2134 le32_to_cpu(hdr->payload_size), in soc_tplg_link_elems_load()
2135 "physical link config")) in soc_tplg_link_elems_load()
2136 return -EINVAL; in soc_tplg_link_elems_load()
2138 /* config physical DAI links */ in soc_tplg_link_elems_load()
2140 link = (struct snd_soc_tplg_link_config *)tplg->pos; in soc_tplg_link_elems_load()
2141 size = le32_to_cpu(link->size); in soc_tplg_link_elems_load()
2142 if (size == sizeof(*link)) { in soc_tplg_link_elems_load()
2144 _link = link; in soc_tplg_link_elems_load()
2147 ret = link_new_ver(tplg, link, &_link); in soc_tplg_link_elems_load()
2159 /* offset by version-specific struct size and in soc_tplg_link_elems_load()
2162 tplg->pos += size + le32_to_cpu(_link->priv.size); in soc_tplg_link_elems_load()
2172 * soc_tplg_dai_config - Find and configure an existing physical DAI.
2174 * @d: physical DAI configs.
2176 * The physical dai should already be registered by the platform driver.
2177 * The platform driver should specify the DAI name and ID for matching.
2183 struct snd_soc_dai *dai; in soc_tplg_dai_config() local
2191 dai_component.dai_name = d->dai_name; in soc_tplg_dai_config()
2192 dai = snd_soc_find_dai(&dai_component); in soc_tplg_dai_config()
2193 if (!dai) { in soc_tplg_dai_config()
2194 dev_err(tplg->dev, "ASoC: physical DAI %s not registered\n", in soc_tplg_dai_config()
2195 d->dai_name); in soc_tplg_dai_config()
2196 return -EINVAL; in soc_tplg_dai_config()
2199 if (le32_to_cpu(d->dai_id) != dai->id) { in soc_tplg_dai_config()
2200 dev_err(tplg->dev, "ASoC: physical DAI %s id mismatch\n", in soc_tplg_dai_config()
2201 d->dai_name); in soc_tplg_dai_config()
2202 return -EINVAL; in soc_tplg_dai_config()
2205 dai_drv = dai->driver; in soc_tplg_dai_config()
2207 return -EINVAL; in soc_tplg_dai_config()
2209 if (d->playback) { in soc_tplg_dai_config()
2210 stream = &dai_drv->playback; in soc_tplg_dai_config()
2211 caps = &d->caps[SND_SOC_TPLG_STREAM_PLAYBACK]; in soc_tplg_dai_config()
2217 if (d->capture) { in soc_tplg_dai_config()
2218 stream = &dai_drv->capture; in soc_tplg_dai_config()
2219 caps = &d->caps[SND_SOC_TPLG_STREAM_CAPTURE]; in soc_tplg_dai_config()
2225 if (d->flag_mask) in soc_tplg_dai_config()
2227 le32_to_cpu(d->flag_mask), in soc_tplg_dai_config()
2228 le32_to_cpu(d->flags)); in soc_tplg_dai_config()
2231 ret = soc_tplg_dai_load(tplg, dai_drv, NULL, dai); in soc_tplg_dai_config()
2233 dev_err(tplg->dev, "ASoC: DAI loading failed\n"); in soc_tplg_dai_config()
2243 /* load physical DAI elements */
2250 count = le32_to_cpu(hdr->count); in soc_tplg_dai_elems_load()
2252 /* config the existing BE DAIs */ in soc_tplg_dai_elems_load()
2254 struct snd_soc_tplg_dai *dai = (struct snd_soc_tplg_dai *)tplg->pos; in soc_tplg_dai_elems_load() local
2257 if (le32_to_cpu(dai->size) != sizeof(*dai)) { in soc_tplg_dai_elems_load()
2258 dev_err(tplg->dev, "ASoC: invalid physical DAI size\n"); in soc_tplg_dai_elems_load()
2259 return -EINVAL; in soc_tplg_dai_elems_load()
2262 ret = soc_tplg_dai_config(tplg, dai); in soc_tplg_dai_elems_load()
2264 dev_err(tplg->dev, "ASoC: failed to configure DAI\n"); in soc_tplg_dai_elems_load()
2268 tplg->pos += (sizeof(*dai) + le32_to_cpu(dai->priv.size)); in soc_tplg_dai_elems_load()
2271 dev_dbg(tplg->dev, "ASoC: Configure %d BE DAIs\n", count); in soc_tplg_dai_elems_load()
2276 * manifest_new_ver - Create a new version of manifest from the old version
2294 size = le32_to_cpu(src->size); in manifest_new_ver()
2296 dev_warn(tplg->dev, "ASoC: invalid manifest size %d\n", in manifest_new_ver()
2299 return -EINVAL; in manifest_new_ver()
2300 src->size = cpu_to_le32(sizeof(*src_v4)); in manifest_new_ver()
2303 dev_warn(tplg->dev, "ASoC: old version of manifest\n"); in manifest_new_ver()
2306 dest = kzalloc(sizeof(*dest) + le32_to_cpu(src_v4->priv.size), in manifest_new_ver()
2309 return -ENOMEM; in manifest_new_ver()
2311 dest->size = cpu_to_le32(sizeof(*dest)); /* size of latest abi version */ in manifest_new_ver()
2312 dest->control_elems = src_v4->control_elems; in manifest_new_ver()
2313 dest->widget_elems = src_v4->widget_elems; in manifest_new_ver()
2314 dest->graph_elems = src_v4->graph_elems; in manifest_new_ver()
2315 dest->pcm_elems = src_v4->pcm_elems; in manifest_new_ver()
2316 dest->dai_link_elems = src_v4->dai_link_elems; in manifest_new_ver()
2317 dest->priv.size = src_v4->priv.size; in manifest_new_ver()
2318 if (dest->priv.size) in manifest_new_ver()
2319 memcpy(dest->priv.data, src_v4->priv.data, in manifest_new_ver()
2320 le32_to_cpu(src_v4->priv.size)); in manifest_new_ver()
2333 manifest = (struct snd_soc_tplg_manifest *)tplg->pos; in soc_tplg_manifest_load()
2336 if (le32_to_cpu(manifest->size) == sizeof(*manifest)) { in soc_tplg_manifest_load()
2348 if (tplg->ops && tplg->ops->manifest) in soc_tplg_manifest_load()
2349 ret = tplg->ops->manifest(tplg->comp, tplg->index, _manifest); in soc_tplg_manifest_load()
2361 if (le32_to_cpu(hdr->size) != sizeof(*hdr)) { in soc_tplg_valid_header()
2362 dev_err(tplg->dev, in soc_tplg_valid_header()
2364 le32_to_cpu(hdr->type), soc_tplg_get_hdr_offset(tplg), in soc_tplg_valid_header()
2365 tplg->fw->size); in soc_tplg_valid_header()
2366 return -EINVAL; in soc_tplg_valid_header()
2369 if (soc_tplg_get_hdr_offset(tplg) + le32_to_cpu(hdr->payload_size) >= tplg->fw->size) { in soc_tplg_valid_header()
2370 dev_err(tplg->dev, in soc_tplg_valid_header()
2372 le32_to_cpu(hdr->type), soc_tplg_get_hdr_offset(tplg), in soc_tplg_valid_header()
2373 hdr->payload_size); in soc_tplg_valid_header()
2374 return -EINVAL; in soc_tplg_valid_header()
2378 if (le32_to_cpu(hdr->magic) == SOC_TPLG_MAGIC_BIG_ENDIAN) { in soc_tplg_valid_header()
2379 dev_err(tplg->dev, in soc_tplg_valid_header()
2381 tplg->pass, hdr->magic, in soc_tplg_valid_header()
2382 soc_tplg_get_hdr_offset(tplg), tplg->fw->size); in soc_tplg_valid_header()
2383 return -EINVAL; in soc_tplg_valid_header()
2386 if (le32_to_cpu(hdr->magic) != SND_SOC_TPLG_MAGIC) { in soc_tplg_valid_header()
2387 dev_err(tplg->dev, in soc_tplg_valid_header()
2389 tplg->pass, hdr->magic, in soc_tplg_valid_header()
2390 soc_tplg_get_hdr_offset(tplg), tplg->fw->size); in soc_tplg_valid_header()
2391 return -EINVAL; in soc_tplg_valid_header()
2395 if (le32_to_cpu(hdr->abi) > SND_SOC_TPLG_ABI_VERSION || in soc_tplg_valid_header()
2396 le32_to_cpu(hdr->abi) < SND_SOC_TPLG_ABI_VERSION_MIN) { in soc_tplg_valid_header()
2397 dev_err(tplg->dev, in soc_tplg_valid_header()
2399 tplg->pass, hdr->abi, in soc_tplg_valid_header()
2401 tplg->fw->size); in soc_tplg_valid_header()
2402 return -EINVAL; in soc_tplg_valid_header()
2405 if (hdr->payload_size == 0) { in soc_tplg_valid_header()
2406 dev_err(tplg->dev, "ASoC: header has 0 size at offset 0x%lx.\n", in soc_tplg_valid_header()
2408 return -EINVAL; in soc_tplg_valid_header()
2422 tplg->pos = tplg->hdr_pos + sizeof(struct snd_soc_tplg_hdr); in soc_tplg_load_header()
2424 tplg->index = le32_to_cpu(hdr->index); in soc_tplg_load_header()
2426 switch (le32_to_cpu(hdr->type)) { in soc_tplg_load_header()
2451 /* physical link configurations */ in soc_tplg_load_header()
2466 if (tplg->pass == hdr_pass) { in soc_tplg_load_header()
2467 dev_dbg(tplg->dev, in soc_tplg_load_header()
2469 hdr->payload_size, hdr->type, hdr->version, in soc_tplg_load_header()
2470 hdr->vendor_type, tplg->pass); in soc_tplg_load_header()
2483 for (tplg->pass = SOC_TPLG_PASS_START; tplg->pass <= SOC_TPLG_PASS_END; tplg->pass++) { in soc_tplg_process_headers()
2486 tplg->hdr_pos = tplg->fw->data; in soc_tplg_process_headers()
2487 hdr = (struct snd_soc_tplg_hdr *)tplg->hdr_pos; in soc_tplg_process_headers()
2499 if (ret != -EPROBE_DEFER) { in soc_tplg_process_headers()
2500 dev_err(tplg->dev, in soc_tplg_process_headers()
2508 tplg->hdr_pos += le32_to_cpu(hdr->payload_size) + in soc_tplg_process_headers()
2510 hdr = (struct snd_soc_tplg_hdr *)tplg->hdr_pos; in soc_tplg_process_headers()
2541 * comp - needs to exist to keep and reference data while parsing in snd_soc_tplg_component_load()
2542 * comp->card - used for setting card related parameters in snd_soc_tplg_component_load()
2543 * comp->card->dev - used for resource management and prints in snd_soc_tplg_component_load()
2544 * fw - we need it, as it is the very thing we parse in snd_soc_tplg_component_load()
2546 if (!comp || !comp->card || !comp->card->dev || !fw) in snd_soc_tplg_component_load()
2547 return -EINVAL; in snd_soc_tplg_component_load()
2552 tplg.dev = comp->card->dev; in snd_soc_tplg_component_load()
2556 tplg.io_ops = ops->io_ops; in snd_soc_tplg_component_load()
2557 tplg.io_ops_count = ops->io_ops_count; in snd_soc_tplg_component_load()
2558 tplg.bytes_ext_ops = ops->bytes_ext_ops; in snd_soc_tplg_component_load()
2559 tplg.bytes_ext_ops_count = ops->bytes_ext_ops_count; in snd_soc_tplg_component_load()
2578 for (pass = SOC_TPLG_PASS_END; pass >= SOC_TPLG_PASS_START; pass--) { in snd_soc_tplg_component_remove()
2581 list_for_each_entry_safe(dobj, next_dobj, &comp->dobj_list, in snd_soc_tplg_component_remove()
2584 switch (dobj->type) { in snd_soc_tplg_component_remove()
2610 dev_err(comp->dev, "ASoC: invalid component type %d for removal\n", in snd_soc_tplg_component_remove()
2611 dobj->type); in snd_soc_tplg_component_remove()
2617 /* let caller know if FW can be freed when no objects are left */ in snd_soc_tplg_component_remove()
2618 return !list_empty(&comp->dobj_list); in snd_soc_tplg_component_remove()