Lines Matching +full:dont +full:- +full:validate

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>
79 /* check we dont overflow the data for this control chunk */
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_control_err()
228 name, hdr->ops.get, hdr->ops.put, hdr->ops.info, in soc_control_err()
238 if (tplg->ops && tplg->ops->vendor_load) in soc_tplg_vendor_load()
239 ret = tplg->ops->vendor_load(tplg->comp, tplg->index, hdr); in soc_tplg_vendor_load()
241 dev_err(tplg->dev, "ASoC: no vendor load callback for ID %d\n", in soc_tplg_vendor_load()
242 hdr->vendor_type); in soc_tplg_vendor_load()
243 return -EINVAL; in soc_tplg_vendor_load()
247 dev_err(tplg->dev, in soc_tplg_vendor_load()
251 hdr->type, hdr->vendor_type); in soc_tplg_vendor_load()
260 if (tplg->ops && tplg->ops->widget_load) in soc_tplg_widget_load()
261 return tplg->ops->widget_load(tplg->comp, tplg->index, w, in soc_tplg_widget_load()
272 if (tplg->ops && tplg->ops->widget_ready) in soc_tplg_widget_ready()
273 return tplg->ops->widget_ready(tplg->comp, tplg->index, w, in soc_tplg_widget_ready()
284 if (tplg->ops && tplg->ops->dai_load) in soc_tplg_dai_load()
285 return tplg->ops->dai_load(tplg->comp, tplg->index, dai_drv, in soc_tplg_dai_load()
295 if (tplg->ops && tplg->ops->link_load) in soc_tplg_dai_link_load()
296 return tplg->ops->link_load(tplg->comp, tplg->index, link, cfg); in soc_tplg_dai_link_load()
304 if (tplg->ops && tplg->ops->complete) in soc_tplg_complete()
305 return tplg->ops->complete(tplg->comp); in soc_tplg_complete()
317 *kcontrol = snd_soc_cnew(control_new, data, control_new->name, prefix); in soc_tplg_add_dcontrol()
320 control_new->name); in soc_tplg_add_dcontrol()
321 return -ENOMEM; in soc_tplg_add_dcontrol()
327 control_new->name, err); in soc_tplg_add_dcontrol()
338 struct snd_soc_component *comp = tplg->comp; in soc_tplg_add_kcontrol()
340 return soc_tplg_add_dcontrol(comp->card->snd_card, in soc_tplg_add_kcontrol()
341 tplg->dev, k, comp->name_prefix, comp, kcontrol); in soc_tplg_add_kcontrol()
348 struct snd_card *card = comp->card->snd_card; in soc_tplg_remove_kcontrol()
353 if (dobj->unload) in soc_tplg_remove_kcontrol()
354 dobj->unload(comp, dobj); in soc_tplg_remove_kcontrol()
356 snd_ctl_remove(card, dobj->control.kcontrol); in soc_tplg_remove_kcontrol()
357 list_del(&dobj->list); in soc_tplg_remove_kcontrol()
367 if (dobj->unload) in soc_tplg_remove_route()
368 dobj->unload(comp, dobj); in soc_tplg_remove_route()
370 list_del(&dobj->list); in soc_tplg_remove_route()
373 /* remove a widget and it's kcontrols - routes must be removed first */
377 struct snd_card *card = comp->card->snd_card; in soc_tplg_remove_widget()
385 if (dobj->unload) in soc_tplg_remove_widget()
386 dobj->unload(comp, dobj); in soc_tplg_remove_widget()
388 if (w->kcontrols) in soc_tplg_remove_widget()
389 for (i = 0; i < w->num_kcontrols; i++) in soc_tplg_remove_widget()
390 snd_ctl_remove(card, w->kcontrols[i]); in soc_tplg_remove_widget()
392 list_del(&dobj->list); in soc_tplg_remove_widget()
394 /* widget w is freed by soc-dapm.c */ in soc_tplg_remove_widget()
408 if (dobj->unload) in soc_tplg_remove_dai()
409 dobj->unload(comp, dobj); in soc_tplg_remove_dai()
412 if (dai->driver == dai_drv) in soc_tplg_remove_dai()
415 list_del(&dobj->list); in soc_tplg_remove_dai()
428 if (dobj->unload) in soc_tplg_remove_link()
429 dobj->unload(comp, dobj); in soc_tplg_remove_link()
431 list_del(&dobj->list); in soc_tplg_remove_link()
434 if (!link->ignore) in soc_tplg_remove_link()
435 snd_soc_remove_pcm_runtime(comp->card, in soc_tplg_remove_link()
436 snd_soc_get_pcm_runtime(comp->card, link)); in soc_tplg_remove_link()
446 if (dobj->unload) in remove_backend_link()
447 dobj->unload(comp, dobj); in remove_backend_link()
454 dobj->type = SND_SOC_DOBJ_NONE; in remove_backend_link()
455 list_del(&dobj->list); in remove_backend_link()
467 if (le32_to_cpu(hdr->ops.info) == SND_SOC_TPLG_CTL_BYTES in soc_tplg_kcontrol_bind_io()
468 && k->iface & SNDRV_CTL_ELEM_IFACE_MIXER in soc_tplg_kcontrol_bind_io()
469 && (k->access & SNDRV_CTL_ELEM_ACCESS_TLV_READ in soc_tplg_kcontrol_bind_io()
470 || k->access & SNDRV_CTL_ELEM_ACCESS_TLV_WRITE) in soc_tplg_kcontrol_bind_io()
471 && k->access & SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK) { in soc_tplg_kcontrol_bind_io()
475 sbe = (struct soc_bytes_ext *)k->private_value; in soc_tplg_kcontrol_bind_io()
481 k->info = snd_soc_bytes_info_ext; in soc_tplg_kcontrol_bind_io()
482 k->tlv.c = snd_soc_bytes_tlv_callback; in soc_tplg_kcontrol_bind_io()
485 * When a topology-based implementation abuses the in soc_tplg_kcontrol_bind_io()
489 * return an -EINVAL error and prevent the card from in soc_tplg_kcontrol_bind_io()
492 if (sbe->max > 512) in soc_tplg_kcontrol_bind_io()
493 k->access |= SNDRV_CTL_ELEM_ACCESS_SKIP_CHECK; in soc_tplg_kcontrol_bind_io()
495 ext_ops = tplg->bytes_ext_ops; in soc_tplg_kcontrol_bind_io()
496 num_ops = tplg->bytes_ext_ops_count; in soc_tplg_kcontrol_bind_io()
498 if (!sbe->put && in soc_tplg_kcontrol_bind_io()
499 ext_ops[i].id == le32_to_cpu(be->ext_ops.put)) in soc_tplg_kcontrol_bind_io()
500 sbe->put = ext_ops[i].put; in soc_tplg_kcontrol_bind_io()
501 if (!sbe->get && in soc_tplg_kcontrol_bind_io()
502 ext_ops[i].id == le32_to_cpu(be->ext_ops.get)) in soc_tplg_kcontrol_bind_io()
503 sbe->get = ext_ops[i].get; in soc_tplg_kcontrol_bind_io()
506 if ((k->access & SNDRV_CTL_ELEM_ACCESS_TLV_READ) && !sbe->get) in soc_tplg_kcontrol_bind_io()
507 return -EINVAL; in soc_tplg_kcontrol_bind_io()
508 if ((k->access & SNDRV_CTL_ELEM_ACCESS_TLV_WRITE) && !sbe->put) in soc_tplg_kcontrol_bind_io()
509 return -EINVAL; in soc_tplg_kcontrol_bind_io()
514 ops = tplg->io_ops; in soc_tplg_kcontrol_bind_io()
515 num_ops = tplg->io_ops_count; in soc_tplg_kcontrol_bind_io()
518 if (k->put == NULL && ops[i].id == le32_to_cpu(hdr->ops.put)) in soc_tplg_kcontrol_bind_io()
519 k->put = ops[i].put; in soc_tplg_kcontrol_bind_io()
520 if (k->get == NULL && ops[i].id == le32_to_cpu(hdr->ops.get)) in soc_tplg_kcontrol_bind_io()
521 k->get = ops[i].get; in soc_tplg_kcontrol_bind_io()
522 if (k->info == NULL && ops[i].id == le32_to_cpu(hdr->ops.info)) in soc_tplg_kcontrol_bind_io()
523 k->info = ops[i].info; in soc_tplg_kcontrol_bind_io()
527 if (k->put && k->get && k->info) in soc_tplg_kcontrol_bind_io()
535 if (k->put == NULL && ops[i].id == le32_to_cpu(hdr->ops.put)) in soc_tplg_kcontrol_bind_io()
536 k->put = ops[i].put; in soc_tplg_kcontrol_bind_io()
537 if (k->get == NULL && ops[i].id == le32_to_cpu(hdr->ops.get)) in soc_tplg_kcontrol_bind_io()
538 k->get = ops[i].get; in soc_tplg_kcontrol_bind_io()
539 if (k->info == NULL && ops[i].id == le32_to_cpu(hdr->ops.info)) in soc_tplg_kcontrol_bind_io()
540 k->info = ops[i].info; in soc_tplg_kcontrol_bind_io()
544 if (k->put && k->get && k->info) in soc_tplg_kcontrol_bind_io()
548 return -EINVAL; in soc_tplg_kcontrol_bind_io()
558 w->event = NULL; in snd_soc_tplg_widget_bind_event()
563 /* found - so assign event */ in snd_soc_tplg_widget_bind_event()
564 w->event = events[i].event_handler; in snd_soc_tplg_widget_bind_event()
570 return -EINVAL; in snd_soc_tplg_widget_bind_event()
580 if (tplg->ops && tplg->ops->control_load) in soc_tplg_control_load()
581 ret = tplg->ops->control_load(tplg->comp, tplg->index, k, hdr); in soc_tplg_control_load()
584 dev_err(tplg->dev, "ASoC: failed to init %s\n", hdr->name); in soc_tplg_control_load()
596 p = devm_kzalloc(tplg->dev, item_len + 2 * sizeof(unsigned int), GFP_KERNEL); in soc_tplg_create_tlv_db_scale()
598 return -ENOMEM; in soc_tplg_create_tlv_db_scale()
602 p[2] = le32_to_cpu(scale->min); in soc_tplg_create_tlv_db_scale()
603 p[3] = (le32_to_cpu(scale->step) & TLV_DB_SCALE_MASK) in soc_tplg_create_tlv_db_scale()
604 | (le32_to_cpu(scale->mute) ? TLV_DB_SCALE_MUTE : 0); in soc_tplg_create_tlv_db_scale()
606 kc->tlv.p = (void *)p; in soc_tplg_create_tlv_db_scale()
614 u32 access = le32_to_cpu(tc->access); in soc_tplg_create_tlv()
620 tplg_tlv = &tc->tlv; in soc_tplg_create_tlv()
621 switch (le32_to_cpu(tplg_tlv->type)) { in soc_tplg_create_tlv()
624 &tplg_tlv->scale); in soc_tplg_create_tlv()
628 dev_dbg(tplg->dev, "Unsupported TLV type %d\n", in soc_tplg_create_tlv()
629 tplg_tlv->type); in soc_tplg_create_tlv()
630 return -EINVAL; in soc_tplg_create_tlv()
643 mc = (struct snd_soc_tplg_mixer_control *)tplg->pos; in soc_tplg_control_dmixer_create()
645 /* validate kcontrol */ in soc_tplg_control_dmixer_create()
646 if (strnlen(mc->hdr.name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN) == SNDRV_CTL_ELEM_ID_NAME_MAXLEN) in soc_tplg_control_dmixer_create()
647 return -EINVAL; in soc_tplg_control_dmixer_create()
649 sm = devm_kzalloc(tplg->dev, sizeof(*sm), GFP_KERNEL); in soc_tplg_control_dmixer_create()
651 return -ENOMEM; in soc_tplg_control_dmixer_create()
653 tplg->pos += sizeof(struct snd_soc_tplg_mixer_control) + le32_to_cpu(mc->priv.size); in soc_tplg_control_dmixer_create()
655 dev_dbg(tplg->dev, "ASoC: adding mixer kcontrol %s with access 0x%x\n", in soc_tplg_control_dmixer_create()
656 mc->hdr.name, mc->hdr.access); in soc_tplg_control_dmixer_create()
658 kc->name = devm_kstrdup(tplg->dev, mc->hdr.name, GFP_KERNEL); in soc_tplg_control_dmixer_create()
659 if (!kc->name) in soc_tplg_control_dmixer_create()
660 return -ENOMEM; in soc_tplg_control_dmixer_create()
661 kc->private_value = (long)sm; in soc_tplg_control_dmixer_create()
662 kc->iface = SNDRV_CTL_ELEM_IFACE_MIXER; in soc_tplg_control_dmixer_create()
663 kc->access = le32_to_cpu(mc->hdr.access); in soc_tplg_control_dmixer_create()
666 sm->reg = tplg_chan_get_reg(tplg, mc->channel, SNDRV_CHMAP_FL); in soc_tplg_control_dmixer_create()
667 sm->rreg = tplg_chan_get_reg(tplg, mc->channel, SNDRV_CHMAP_FR); in soc_tplg_control_dmixer_create()
668 sm->shift = tplg_chan_get_shift(tplg, mc->channel, SNDRV_CHMAP_FL); in soc_tplg_control_dmixer_create()
669 sm->rshift = tplg_chan_get_shift(tplg, mc->channel, SNDRV_CHMAP_FR); in soc_tplg_control_dmixer_create()
671 sm->max = le32_to_cpu(mc->max); in soc_tplg_control_dmixer_create()
672 sm->min = le32_to_cpu(mc->min); in soc_tplg_control_dmixer_create()
673 sm->invert = le32_to_cpu(mc->invert); in soc_tplg_control_dmixer_create()
674 sm->platform_max = le32_to_cpu(mc->platform_max); in soc_tplg_control_dmixer_create()
675 sm->num_channels = le32_to_cpu(mc->num_channels); in soc_tplg_control_dmixer_create()
678 err = soc_tplg_kcontrol_bind_io(&mc->hdr, kc, tplg); in soc_tplg_control_dmixer_create()
680 soc_control_err(tplg, &mc->hdr, mc->hdr.name); in soc_tplg_control_dmixer_create()
685 err = soc_tplg_create_tlv(tplg, kc, &mc->hdr); in soc_tplg_control_dmixer_create()
687 dev_err(tplg->dev, "ASoC: failed to create TLV %s\n", mc->hdr.name); in soc_tplg_control_dmixer_create()
692 return soc_tplg_control_load(tplg, kc, &mc->hdr); in soc_tplg_control_dmixer_create()
700 if (le32_to_cpu(ec->items) > ARRAY_SIZE(ec->texts)) in soc_tplg_denum_create_texts()
701 return -EINVAL; in soc_tplg_denum_create_texts()
703 se->dobj.control.dtexts = in soc_tplg_denum_create_texts()
704 devm_kcalloc(tplg->dev, le32_to_cpu(ec->items), sizeof(char *), GFP_KERNEL); in soc_tplg_denum_create_texts()
705 if (se->dobj.control.dtexts == NULL) in soc_tplg_denum_create_texts()
706 return -ENOMEM; in soc_tplg_denum_create_texts()
708 for (i = 0; i < le32_to_cpu(ec->items); i++) { in soc_tplg_denum_create_texts()
710 if (strnlen(ec->texts[i], SNDRV_CTL_ELEM_ID_NAME_MAXLEN) == in soc_tplg_denum_create_texts()
712 ret = -EINVAL; in soc_tplg_denum_create_texts()
716 se->dobj.control.dtexts[i] = devm_kstrdup(tplg->dev, ec->texts[i], GFP_KERNEL); in soc_tplg_denum_create_texts()
717 if (!se->dobj.control.dtexts[i]) { in soc_tplg_denum_create_texts()
718 ret = -ENOMEM; in soc_tplg_denum_create_texts()
723 se->items = le32_to_cpu(ec->items); in soc_tplg_denum_create_texts()
724 se->texts = (const char * const *)se->dobj.control.dtexts; in soc_tplg_denum_create_texts()
738 * values instead of using ARRAY_SIZE(ec->values) due to the fact that in soc_tplg_denum_create_values()
742 if (le32_to_cpu(ec->items) > SND_SOC_TPLG_NUM_TEXTS) in soc_tplg_denum_create_values()
743 return -EINVAL; in soc_tplg_denum_create_values()
745 se->dobj.control.dvalues = devm_kcalloc(tplg->dev, le32_to_cpu(ec->items), in soc_tplg_denum_create_values()
746 sizeof(*se->dobj.control.dvalues), in soc_tplg_denum_create_values()
748 if (!se->dobj.control.dvalues) in soc_tplg_denum_create_values()
749 return -ENOMEM; in soc_tplg_denum_create_values()
751 /* convert from little-endian */ in soc_tplg_denum_create_values()
752 for (i = 0; i < le32_to_cpu(ec->items); i++) { in soc_tplg_denum_create_values()
753 se->dobj.control.dvalues[i] = le32_to_cpu(ec->values[i]); in soc_tplg_denum_create_values()
756 se->items = le32_to_cpu(ec->items); in soc_tplg_denum_create_values()
757 se->values = (const unsigned int *)se->dobj.control.dvalues; in soc_tplg_denum_create_values()
767 ec = (struct snd_soc_tplg_enum_control *)tplg->pos; in soc_tplg_control_denum_create()
769 /* validate kcontrol */ in soc_tplg_control_denum_create()
770 if (strnlen(ec->hdr.name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN) == SNDRV_CTL_ELEM_ID_NAME_MAXLEN) in soc_tplg_control_denum_create()
771 return -EINVAL; in soc_tplg_control_denum_create()
773 se = devm_kzalloc(tplg->dev, sizeof(*se), GFP_KERNEL); in soc_tplg_control_denum_create()
775 return -ENOMEM; in soc_tplg_control_denum_create()
777 tplg->pos += (sizeof(struct snd_soc_tplg_enum_control) + le32_to_cpu(ec->priv.size)); in soc_tplg_control_denum_create()
779 dev_dbg(tplg->dev, "ASoC: adding enum kcontrol %s size %d\n", ec->hdr.name, ec->items); in soc_tplg_control_denum_create()
781 kc->name = devm_kstrdup(tplg->dev, ec->hdr.name, GFP_KERNEL); in soc_tplg_control_denum_create()
782 if (!kc->name) in soc_tplg_control_denum_create()
783 return -ENOMEM; in soc_tplg_control_denum_create()
784 kc->private_value = (long)se; in soc_tplg_control_denum_create()
785 kc->iface = SNDRV_CTL_ELEM_IFACE_MIXER; in soc_tplg_control_denum_create()
786 kc->access = le32_to_cpu(ec->hdr.access); in soc_tplg_control_denum_create()
789 se->reg = tplg_chan_get_reg(tplg, ec->channel, SNDRV_CHMAP_FL); in soc_tplg_control_denum_create()
790 se->shift_l = tplg_chan_get_shift(tplg, ec->channel, SNDRV_CHMAP_FL); in soc_tplg_control_denum_create()
791 se->shift_r = tplg_chan_get_shift(tplg, ec->channel, SNDRV_CHMAP_FR); in soc_tplg_control_denum_create()
793 se->mask = le32_to_cpu(ec->mask); in soc_tplg_control_denum_create()
795 switch (le32_to_cpu(ec->hdr.ops.info)) { in soc_tplg_control_denum_create()
800 dev_err(tplg->dev, "ASoC: could not create values for %s\n", ec->hdr.name); in soc_tplg_control_denum_create()
809 dev_err(tplg->dev, "ASoC: could not create texts for %s\n", ec->hdr.name); in soc_tplg_control_denum_create()
814 dev_err(tplg->dev, "ASoC: invalid enum control type %d for %s\n", in soc_tplg_control_denum_create()
815 ec->hdr.ops.info, ec->hdr.name); in soc_tplg_control_denum_create()
816 return -EINVAL; in soc_tplg_control_denum_create()
820 err = soc_tplg_kcontrol_bind_io(&ec->hdr, kc, tplg); in soc_tplg_control_denum_create()
822 soc_control_err(tplg, &ec->hdr, ec->hdr.name); in soc_tplg_control_denum_create()
827 return soc_tplg_control_load(tplg, kc, &ec->hdr); in soc_tplg_control_denum_create()
836 be = (struct snd_soc_tplg_bytes_control *)tplg->pos; in soc_tplg_control_dbytes_create()
838 /* validate kcontrol */ in soc_tplg_control_dbytes_create()
839 if (strnlen(be->hdr.name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN) == SNDRV_CTL_ELEM_ID_NAME_MAXLEN) in soc_tplg_control_dbytes_create()
840 return -EINVAL; in soc_tplg_control_dbytes_create()
842 sbe = devm_kzalloc(tplg->dev, sizeof(*sbe), GFP_KERNEL); in soc_tplg_control_dbytes_create()
844 return -ENOMEM; in soc_tplg_control_dbytes_create()
846 tplg->pos += (sizeof(struct snd_soc_tplg_bytes_control) + le32_to_cpu(be->priv.size)); in soc_tplg_control_dbytes_create()
848 dev_dbg(tplg->dev, "ASoC: adding bytes kcontrol %s with access 0x%x\n", in soc_tplg_control_dbytes_create()
849 be->hdr.name, be->hdr.access); in soc_tplg_control_dbytes_create()
851 kc->name = devm_kstrdup(tplg->dev, be->hdr.name, GFP_KERNEL); in soc_tplg_control_dbytes_create()
852 if (!kc->name) in soc_tplg_control_dbytes_create()
853 return -ENOMEM; in soc_tplg_control_dbytes_create()
854 kc->private_value = (long)sbe; in soc_tplg_control_dbytes_create()
855 kc->iface = SNDRV_CTL_ELEM_IFACE_MIXER; in soc_tplg_control_dbytes_create()
856 kc->access = le32_to_cpu(be->hdr.access); in soc_tplg_control_dbytes_create()
858 sbe->max = le32_to_cpu(be->max); in soc_tplg_control_dbytes_create()
861 err = soc_tplg_kcontrol_bind_io(&be->hdr, kc, tplg); in soc_tplg_control_dbytes_create()
863 soc_control_err(tplg, &be->hdr, be->hdr.name); in soc_tplg_control_dbytes_create()
868 return soc_tplg_control_load(tplg, kc, &be->hdr); in soc_tplg_control_dbytes_create()
880 return -EINVAL; in soc_tplg_dbytes_create()
889 INIT_LIST_HEAD(&sbe->dobj.list); in soc_tplg_dbytes_create()
890 sbe->dobj.type = SND_SOC_DOBJ_BYTES; in soc_tplg_dbytes_create()
891 sbe->dobj.index = tplg->index; in soc_tplg_dbytes_create()
892 if (tplg->ops) in soc_tplg_dbytes_create()
893 sbe->dobj.unload = tplg->ops->control_unload; in soc_tplg_dbytes_create()
896 ret = soc_tplg_add_kcontrol(tplg, &kc, &sbe->dobj.control.kcontrol); in soc_tplg_dbytes_create()
900 list_add(&sbe->dobj.list, &tplg->comp->dobj_list); in soc_tplg_dbytes_create()
914 return -EINVAL; in soc_tplg_dmixer_create()
923 INIT_LIST_HEAD(&sm->dobj.list); in soc_tplg_dmixer_create()
924 sm->dobj.type = SND_SOC_DOBJ_MIXER; in soc_tplg_dmixer_create()
925 sm->dobj.index = tplg->index; in soc_tplg_dmixer_create()
926 if (tplg->ops) in soc_tplg_dmixer_create()
927 sm->dobj.unload = tplg->ops->control_unload; in soc_tplg_dmixer_create()
930 ret = soc_tplg_add_kcontrol(tplg, &kc, &sm->dobj.control.kcontrol); in soc_tplg_dmixer_create()
934 list_add(&sm->dobj.list, &tplg->comp->dobj_list); in soc_tplg_dmixer_create()
948 return -EINVAL; in soc_tplg_denum_create()
957 INIT_LIST_HEAD(&se->dobj.list); in soc_tplg_denum_create()
958 se->dobj.type = SND_SOC_DOBJ_ENUM; in soc_tplg_denum_create()
959 se->dobj.index = tplg->index; in soc_tplg_denum_create()
960 if (tplg->ops) in soc_tplg_denum_create()
961 se->dobj.unload = tplg->ops->control_unload; in soc_tplg_denum_create()
964 ret = soc_tplg_add_kcontrol(tplg, &kc, &se->dobj.control.kcontrol); in soc_tplg_denum_create()
968 list_add(&se->dobj.list, &tplg->comp->dobj_list); in soc_tplg_denum_create()
979 dev_dbg(tplg->dev, "ASoC: adding %d kcontrols at 0x%lx\n", hdr->count, in soc_tplg_kcontrol_elems_load()
982 for (i = 0; i < le32_to_cpu(hdr->count); i++) { in soc_tplg_kcontrol_elems_load()
983 struct snd_soc_tplg_ctl_hdr *control_hdr = (struct snd_soc_tplg_ctl_hdr *)tplg->pos; in soc_tplg_kcontrol_elems_load()
985 if (le32_to_cpu(control_hdr->size) != sizeof(*control_hdr)) { in soc_tplg_kcontrol_elems_load()
986 dev_err(tplg->dev, "ASoC: invalid control size\n"); in soc_tplg_kcontrol_elems_load()
987 return -EINVAL; in soc_tplg_kcontrol_elems_load()
990 switch (le32_to_cpu(control_hdr->type)) { in soc_tplg_kcontrol_elems_load()
992 ret = soc_tplg_dmixer_create(tplg, le32_to_cpu(hdr->payload_size)); in soc_tplg_kcontrol_elems_load()
995 ret = soc_tplg_denum_create(tplg, le32_to_cpu(hdr->payload_size)); in soc_tplg_kcontrol_elems_load()
998 ret = soc_tplg_dbytes_create(tplg, le32_to_cpu(hdr->payload_size)); in soc_tplg_kcontrol_elems_load()
1001 ret = -EINVAL; in soc_tplg_kcontrol_elems_load()
1006 dev_err(tplg->dev, "ASoC: invalid control type: %d, index: %d at 0x%lx\n", in soc_tplg_kcontrol_elems_load()
1007 control_hdr->type, i, soc_tplg_get_offset(tplg)); in soc_tplg_kcontrol_elems_load()
1019 if (tplg->ops && tplg->ops->dapm_route_load) in soc_tplg_add_route()
1020 return tplg->ops->dapm_route_load(tplg->comp, tplg->index, in soc_tplg_add_route()
1029 struct snd_soc_dapm_context *dapm = &tplg->comp->dapm; in soc_tplg_dapm_graph_elems_load()
1036 count = le32_to_cpu(hdr->count); in soc_tplg_dapm_graph_elems_load()
1040 count, le32_to_cpu(hdr->payload_size), "graph")) in soc_tplg_dapm_graph_elems_load()
1041 return -EINVAL; in soc_tplg_dapm_graph_elems_load()
1043 dev_dbg(tplg->dev, "ASoC: adding %d DAPM routes for index %d\n", count, in soc_tplg_dapm_graph_elems_load()
1044 hdr->index); in soc_tplg_dapm_graph_elems_load()
1047 route = devm_kzalloc(tplg->dev, sizeof(*route), GFP_KERNEL); in soc_tplg_dapm_graph_elems_load()
1049 return -ENOMEM; in soc_tplg_dapm_graph_elems_load()
1050 elem = (struct snd_soc_tplg_dapm_graph_elem *)tplg->pos; in soc_tplg_dapm_graph_elems_load()
1051 tplg->pos += sizeof(struct snd_soc_tplg_dapm_graph_elem); in soc_tplg_dapm_graph_elems_load()
1053 /* validate routes */ in soc_tplg_dapm_graph_elems_load()
1054 if ((strnlen(elem->source, maxlen) == maxlen) || in soc_tplg_dapm_graph_elems_load()
1055 (strnlen(elem->sink, maxlen) == maxlen) || in soc_tplg_dapm_graph_elems_load()
1056 (strnlen(elem->control, maxlen) == maxlen)) { in soc_tplg_dapm_graph_elems_load()
1057 ret = -EINVAL; in soc_tplg_dapm_graph_elems_load()
1061 route->source = devm_kstrdup(tplg->dev, elem->source, GFP_KERNEL); in soc_tplg_dapm_graph_elems_load()
1062 route->sink = devm_kstrdup(tplg->dev, elem->sink, GFP_KERNEL); in soc_tplg_dapm_graph_elems_load()
1063 if (!route->source || !route->sink) { in soc_tplg_dapm_graph_elems_load()
1064 ret = -ENOMEM; in soc_tplg_dapm_graph_elems_load()
1068 if (strnlen(elem->control, maxlen) != 0) { in soc_tplg_dapm_graph_elems_load()
1069 route->control = devm_kstrdup(tplg->dev, elem->control, GFP_KERNEL); in soc_tplg_dapm_graph_elems_load()
1070 if (!route->control) { in soc_tplg_dapm_graph_elems_load()
1071 ret = -ENOMEM; in soc_tplg_dapm_graph_elems_load()
1077 route->dobj.type = SND_SOC_DOBJ_GRAPH; in soc_tplg_dapm_graph_elems_load()
1078 if (tplg->ops) in soc_tplg_dapm_graph_elems_load()
1079 route->dobj.unload = tplg->ops->dapm_route_unload; in soc_tplg_dapm_graph_elems_load()
1080 route->dobj.index = tplg->index; in soc_tplg_dapm_graph_elems_load()
1081 list_add(&route->dobj.list, &tplg->comp->dobj_list); in soc_tplg_dapm_graph_elems_load()
1085 dev_err(tplg->dev, "ASoC: topology: add_route failed: %d\n", ret); in soc_tplg_dapm_graph_elems_load()
1100 struct snd_soc_dapm_context *dapm = &tplg->comp->dapm; in soc_tplg_dapm_widget_create()
1103 struct snd_soc_card *card = tplg->comp->card; in soc_tplg_dapm_widget_create()
1112 if (strnlen(w->name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN) == in soc_tplg_dapm_widget_create()
1114 return -EINVAL; in soc_tplg_dapm_widget_create()
1115 if (strnlen(w->sname, SNDRV_CTL_ELEM_ID_NAME_MAXLEN) == in soc_tplg_dapm_widget_create()
1117 return -EINVAL; in soc_tplg_dapm_widget_create()
1119 dev_dbg(tplg->dev, "ASoC: creating DAPM widget %s id %d\n", in soc_tplg_dapm_widget_create()
1120 w->name, w->id); in soc_tplg_dapm_widget_create()
1125 template.id = get_widget_id(le32_to_cpu(w->id)); in soc_tplg_dapm_widget_create()
1130 template.name = kstrdup(w->name, GFP_KERNEL); in soc_tplg_dapm_widget_create()
1132 return -ENOMEM; in soc_tplg_dapm_widget_create()
1133 template.sname = kstrdup(w->sname, GFP_KERNEL); in soc_tplg_dapm_widget_create()
1135 ret = -ENOMEM; in soc_tplg_dapm_widget_create()
1138 template.reg = le32_to_cpu(w->reg); in soc_tplg_dapm_widget_create()
1139 template.shift = le32_to_cpu(w->shift); in soc_tplg_dapm_widget_create()
1140 template.mask = le32_to_cpu(w->mask); in soc_tplg_dapm_widget_create()
1141 template.subseq = le32_to_cpu(w->subseq); in soc_tplg_dapm_widget_create()
1142 template.on_val = w->invert ? 0 : 1; in soc_tplg_dapm_widget_create()
1143 template.off_val = w->invert ? 1 : 0; in soc_tplg_dapm_widget_create()
1144 template.ignore_suspend = le32_to_cpu(w->ignore_suspend); in soc_tplg_dapm_widget_create()
1145 template.event_flags = le16_to_cpu(w->event_flags); in soc_tplg_dapm_widget_create()
1146 template.dobj.index = tplg->index; in soc_tplg_dapm_widget_create()
1148 tplg->pos += in soc_tplg_dapm_widget_create()
1150 le32_to_cpu(w->priv.size)); in soc_tplg_dapm_widget_create()
1152 if (w->num_kcontrols == 0) { in soc_tplg_dapm_widget_create()
1157 template.num_kcontrols = le32_to_cpu(w->num_kcontrols); in soc_tplg_dapm_widget_create()
1158 kc = devm_kcalloc(tplg->dev, le32_to_cpu(w->num_kcontrols), sizeof(*kc), GFP_KERNEL); in soc_tplg_dapm_widget_create()
1160 ret = -ENOMEM; in soc_tplg_dapm_widget_create()
1164 kcontrol_type = devm_kcalloc(tplg->dev, le32_to_cpu(w->num_kcontrols), sizeof(unsigned int), in soc_tplg_dapm_widget_create()
1167 ret = -ENOMEM; in soc_tplg_dapm_widget_create()
1171 for (i = 0; i < le32_to_cpu(w->num_kcontrols); i++) { in soc_tplg_dapm_widget_create()
1172 control_hdr = (struct snd_soc_tplg_ctl_hdr *)tplg->pos; in soc_tplg_dapm_widget_create()
1174 switch (le32_to_cpu(control_hdr->type)) { in soc_tplg_dapm_widget_create()
1203 dev_err(tplg->dev, "ASoC: invalid widget control type %d:%d:%d\n", in soc_tplg_dapm_widget_create()
1204 control_hdr->ops.get, control_hdr->ops.put, in soc_tplg_dapm_widget_create()
1205 le32_to_cpu(control_hdr->ops.info)); in soc_tplg_dapm_widget_create()
1206 ret = -EINVAL; in soc_tplg_dapm_widget_create()
1212 dev_dbg(tplg->dev, "ASoC: template %s with %d/%d/%d (mixer/enum/bytes) control\n", in soc_tplg_dapm_widget_create()
1213 w->name, mixer_count, enum_count, bytes_count); in soc_tplg_dapm_widget_create()
1231 widget->dobj.type = SND_SOC_DOBJ_WIDGET; in soc_tplg_dapm_widget_create()
1232 widget->dobj.widget.kcontrol_type = kcontrol_type; in soc_tplg_dapm_widget_create()
1233 if (tplg->ops) in soc_tplg_dapm_widget_create()
1234 widget->dobj.unload = tplg->ops->widget_unload; in soc_tplg_dapm_widget_create()
1235 widget->dobj.index = tplg->index; in soc_tplg_dapm_widget_create()
1236 list_add(&widget->dobj.list, &tplg->comp->dobj_list); in soc_tplg_dapm_widget_create()
1248 soc_tplg_remove_widget(widget->dapm->component, &widget->dobj, SOC_TPLG_PASS_WIDGET); in soc_tplg_dapm_widget_create()
1262 count = le32_to_cpu(hdr->count); in soc_tplg_dapm_widget_elems_load()
1264 dev_dbg(tplg->dev, "ASoC: adding %d DAPM widgets\n", count); in soc_tplg_dapm_widget_elems_load()
1267 struct snd_soc_tplg_dapm_widget *widget = (struct snd_soc_tplg_dapm_widget *) tplg->pos; in soc_tplg_dapm_widget_elems_load()
1272 * use sizeof instead of widget->size, as we can't be sure in soc_tplg_dapm_widget_elems_load()
1275 if (soc_tplg_get_offset(tplg) + sizeof(*widget) >= tplg->fw->size) { in soc_tplg_dapm_widget_elems_load()
1276 dev_err(tplg->dev, "ASoC: invalid widget data size\n"); in soc_tplg_dapm_widget_elems_load()
1277 return -EINVAL; in soc_tplg_dapm_widget_elems_load()
1281 if (le32_to_cpu(widget->size) != sizeof(*widget)) { in soc_tplg_dapm_widget_elems_load()
1282 dev_err(tplg->dev, "ASoC: invalid widget size\n"); in soc_tplg_dapm_widget_elems_load()
1283 return -EINVAL; in soc_tplg_dapm_widget_elems_load()
1287 if (soc_tplg_get_offset(tplg) + le32_to_cpu(widget->priv.size) >= tplg->fw->size) { in soc_tplg_dapm_widget_elems_load()
1288 dev_err(tplg->dev, "ASoC: invalid widget private data size\n"); in soc_tplg_dapm_widget_elems_load()
1289 return -EINVAL; in soc_tplg_dapm_widget_elems_load()
1294 dev_err(tplg->dev, "ASoC: failed to load widget %s\n", in soc_tplg_dapm_widget_elems_load()
1295 widget->name); in soc_tplg_dapm_widget_elems_load()
1305 struct snd_soc_card *card = tplg->comp->card; in soc_tplg_dapm_complete()
1312 dev_warn(tplg->dev, "ASoC: Parent card not yet available, widget card binding deferred\n"); in soc_tplg_dapm_complete()
1318 dev_err(tplg->dev, "ASoC: failed to create new widgets %d\n", ret); in soc_tplg_dapm_complete()
1326 stream->stream_name = devm_kstrdup(tplg->dev, caps->name, GFP_KERNEL); in set_stream_info()
1327 if (!stream->stream_name) in set_stream_info()
1328 return -ENOMEM; in set_stream_info()
1330 stream->channels_min = le32_to_cpu(caps->channels_min); in set_stream_info()
1331 stream->channels_max = le32_to_cpu(caps->channels_max); in set_stream_info()
1332 stream->rates = le32_to_cpu(caps->rates); in set_stream_info()
1333 stream->rate_min = le32_to_cpu(caps->rate_min); in set_stream_info()
1334 stream->rate_max = le32_to_cpu(caps->rate_max); in set_stream_info()
1335 stream->formats = le64_to_cpu(caps->formats); in set_stream_info()
1336 stream->sig_bits = le32_to_cpu(caps->sig_bits); in set_stream_info()
1345 dai_drv->symmetric_rate = in set_dai_flags()
1349 dai_drv->symmetric_channels = in set_dai_flags()
1354 dai_drv->symmetric_sample_bits = in set_dai_flags()
1371 snd_soc_component_get_dapm(tplg->comp); in soc_tplg_dai_create()
1374 dai_drv = devm_kzalloc(tplg->dev, sizeof(struct snd_soc_dai_driver), GFP_KERNEL); in soc_tplg_dai_create()
1376 return -ENOMEM; in soc_tplg_dai_create()
1378 if (strlen(pcm->dai_name)) { in soc_tplg_dai_create()
1379 dai_drv->name = devm_kstrdup(tplg->dev, pcm->dai_name, GFP_KERNEL); in soc_tplg_dai_create()
1380 if (!dai_drv->name) { in soc_tplg_dai_create()
1381 ret = -ENOMEM; in soc_tplg_dai_create()
1385 dai_drv->id = le32_to_cpu(pcm->dai_id); in soc_tplg_dai_create()
1387 if (pcm->playback) { in soc_tplg_dai_create()
1388 stream = &dai_drv->playback; in soc_tplg_dai_create()
1389 caps = &pcm->caps[SND_SOC_TPLG_STREAM_PLAYBACK]; in soc_tplg_dai_create()
1395 if (pcm->capture) { in soc_tplg_dai_create()
1396 stream = &dai_drv->capture; in soc_tplg_dai_create()
1397 caps = &pcm->caps[SND_SOC_TPLG_STREAM_CAPTURE]; in soc_tplg_dai_create()
1403 if (pcm->compress) in soc_tplg_dai_create()
1404 dai_drv->ops = &tplg_dai_ops; in soc_tplg_dai_create()
1409 dev_err(tplg->dev, "ASoC: DAI loading failed\n"); in soc_tplg_dai_create()
1413 dai_drv->dobj.index = tplg->index; in soc_tplg_dai_create()
1414 dai_drv->dobj.type = SND_SOC_DOBJ_PCM; in soc_tplg_dai_create()
1415 if (tplg->ops) in soc_tplg_dai_create()
1416 dai_drv->dobj.unload = tplg->ops->dai_unload; in soc_tplg_dai_create()
1417 list_add(&dai_drv->dobj.list, &tplg->comp->dobj_list); in soc_tplg_dai_create()
1420 dai = snd_soc_register_dai(tplg->comp, dai_drv, false); in soc_tplg_dai_create()
1422 return -ENOMEM; in soc_tplg_dai_create()
1427 dev_err(dai->dev, "Failed to create DAI widgets %d\n", ret); in soc_tplg_dai_create()
1442 link->symmetric_rate = in set_link_flags()
1446 link->symmetric_channels = in set_link_flags()
1451 link->symmetric_sample_bits = in set_link_flags()
1456 link->ignore_suspend = in set_link_flags()
1470 link = devm_kzalloc(tplg->dev, sizeof(*link) + (3 * sizeof(*dlc)), GFP_KERNEL); in soc_tplg_fe_link_create()
1472 return -ENOMEM; in soc_tplg_fe_link_create()
1476 link->cpus = &dlc[0]; in soc_tplg_fe_link_create()
1477 link->num_cpus = 1; in soc_tplg_fe_link_create()
1479 link->dobj.index = tplg->index; in soc_tplg_fe_link_create()
1480 link->dobj.type = SND_SOC_DOBJ_DAI_LINK; in soc_tplg_fe_link_create()
1481 if (tplg->ops) in soc_tplg_fe_link_create()
1482 link->dobj.unload = tplg->ops->link_unload; in soc_tplg_fe_link_create()
1484 if (strlen(pcm->pcm_name)) { in soc_tplg_fe_link_create()
1485 link->name = devm_kstrdup(tplg->dev, pcm->pcm_name, GFP_KERNEL); in soc_tplg_fe_link_create()
1486 link->stream_name = devm_kstrdup(tplg->dev, pcm->pcm_name, GFP_KERNEL); in soc_tplg_fe_link_create()
1487 if (!link->name || !link->stream_name) { in soc_tplg_fe_link_create()
1488 ret = -ENOMEM; in soc_tplg_fe_link_create()
1492 link->id = le32_to_cpu(pcm->pcm_id); in soc_tplg_fe_link_create()
1494 if (strlen(pcm->dai_name)) { in soc_tplg_fe_link_create()
1495 link->cpus->dai_name = devm_kstrdup(tplg->dev, pcm->dai_name, GFP_KERNEL); in soc_tplg_fe_link_create()
1496 if (!link->cpus->dai_name) { in soc_tplg_fe_link_create()
1497 ret = -ENOMEM; in soc_tplg_fe_link_create()
1507 link->codecs = &dlc[1]; /* Don't use &snd_soc_dummy_dlc here */ in soc_tplg_fe_link_create()
1508 link->codecs->name = "snd-soc-dummy"; in soc_tplg_fe_link_create()
1509 link->codecs->dai_name = "snd-soc-dummy-dai"; in soc_tplg_fe_link_create()
1510 link->num_codecs = 1; in soc_tplg_fe_link_create()
1512 link->platforms = &dlc[2]; /* Don't use &snd_soc_dummy_dlc here */ in soc_tplg_fe_link_create()
1513 link->platforms->name = "snd-soc-dummy"; in soc_tplg_fe_link_create()
1514 link->num_platforms = 1; in soc_tplg_fe_link_create()
1517 link->dynamic = 1; in soc_tplg_fe_link_create()
1518 link->ignore_pmdown_time = 1; in soc_tplg_fe_link_create()
1519 link->playback_only = le32_to_cpu(pcm->playback) && !le32_to_cpu(pcm->capture); in soc_tplg_fe_link_create()
1520 link->capture_only = !le32_to_cpu(pcm->playback) && le32_to_cpu(pcm->capture); in soc_tplg_fe_link_create()
1521 if (pcm->flag_mask) in soc_tplg_fe_link_create()
1523 le32_to_cpu(pcm->flag_mask), in soc_tplg_fe_link_create()
1524 le32_to_cpu(pcm->flags)); in soc_tplg_fe_link_create()
1529 dev_err(tplg->dev, "ASoC: FE link loading failed\n"); in soc_tplg_fe_link_create()
1533 ret = snd_soc_add_pcm_runtimes(tplg->comp->card, link, 1); in soc_tplg_fe_link_create()
1535 if (ret != -EPROBE_DEFER) in soc_tplg_fe_link_create()
1536 dev_err(tplg->dev, "ASoC: adding FE link failed\n"); in soc_tplg_fe_link_create()
1540 list_add(&link->dobj.list, &tplg->comp->dobj_list); in soc_tplg_fe_link_create()
1569 count = le32_to_cpu(hdr->count); in soc_tplg_pcm_elems_load()
1572 pcm = (struct snd_soc_tplg_pcm *)tplg->pos; in soc_tplg_pcm_elems_load()
1573 size = le32_to_cpu(pcm->size); in soc_tplg_pcm_elems_load()
1575 dev_err(tplg->dev, "ASoC: invalid size %d for PCM elems\n", in soc_tplg_pcm_elems_load()
1577 return -EINVAL; in soc_tplg_pcm_elems_load()
1582 le32_to_cpu(hdr->payload_size), in soc_tplg_pcm_elems_load()
1584 return -EINVAL; in soc_tplg_pcm_elems_load()
1587 pcm = (struct snd_soc_tplg_pcm *)tplg->pos; in soc_tplg_pcm_elems_load()
1588 size = le32_to_cpu(pcm->size); in soc_tplg_pcm_elems_load()
1594 return -EINVAL; in soc_tplg_pcm_elems_load()
1601 /* offset by version-specific struct size and in soc_tplg_pcm_elems_load()
1604 tplg->pos += size + le32_to_cpu(pcm->priv.size); in soc_tplg_pcm_elems_load()
1607 dev_dbg(tplg->dev, "ASoC: adding %d PCM DAIs\n", count); in soc_tplg_pcm_elems_load()
1613 * set_link_hw_format - Set the HW audio format of the physical DAI link.
1629 for (i = 0; i < le32_to_cpu(cfg->num_hw_configs); i++) { in set_link_hw_format()
1630 hw_config = &cfg->hw_config[i]; in set_link_hw_format()
1631 if (hw_config->id != cfg->default_hw_config_id) in set_link_hw_format()
1634 link->dai_fmt = le32_to_cpu(hw_config->fmt) & in set_link_hw_format()
1638 switch (hw_config->clock_gated) { in set_link_hw_format()
1640 link->dai_fmt |= SND_SOC_DAIFMT_GATED; in set_link_hw_format()
1644 link->dai_fmt |= SND_SOC_DAIFMT_CONT; in set_link_hw_format()
1653 invert_bclk = hw_config->invert_bclk; in set_link_hw_format()
1654 invert_fsync = hw_config->invert_fsync; in set_link_hw_format()
1656 link->dai_fmt |= SND_SOC_DAIFMT_NB_NF; in set_link_hw_format()
1658 link->dai_fmt |= SND_SOC_DAIFMT_NB_IF; in set_link_hw_format()
1660 link->dai_fmt |= SND_SOC_DAIFMT_IB_NF; in set_link_hw_format()
1662 link->dai_fmt |= SND_SOC_DAIFMT_IB_IF; in set_link_hw_format()
1665 bclk_provider = (hw_config->bclk_provider == in set_link_hw_format()
1667 fsync_provider = (hw_config->fsync_provider == in set_link_hw_format()
1670 link->dai_fmt |= SND_SOC_DAIFMT_CBP_CFP; in set_link_hw_format()
1672 link->dai_fmt |= SND_SOC_DAIFMT_CBC_CFP; in set_link_hw_format()
1674 link->dai_fmt |= SND_SOC_DAIFMT_CBP_CFC; in set_link_hw_format()
1676 link->dai_fmt |= SND_SOC_DAIFMT_CBC_CFC; in set_link_hw_format()
1681 * snd_soc_find_dai_link - Find a DAI link
1702 struct snd_soc_dai_link *link = rtd->dai_link; in snd_soc_find_dai_link()
1704 if (link->id != id) in snd_soc_find_dai_link()
1707 if (name && (!link->name || !strstr(link->name, name))) in snd_soc_find_dai_link()
1710 if (stream_name && (!link->stream_name || in snd_soc_find_dai_link()
1711 !strstr(link->stream_name, stream_name))) in snd_soc_find_dai_link()
1729 len = strnlen(cfg->name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN); in soc_tplg_link_config()
1731 return -EINVAL; in soc_tplg_link_config()
1733 name = cfg->name; in soc_tplg_link_config()
1737 len = strnlen(cfg->stream_name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN); in soc_tplg_link_config()
1739 return -EINVAL; in soc_tplg_link_config()
1741 stream_name = cfg->stream_name; in soc_tplg_link_config()
1745 link = snd_soc_find_dai_link(tplg->comp->card, le32_to_cpu(cfg->id), in soc_tplg_link_config()
1748 dev_err(tplg->dev, "ASoC: physical link %s (id %d) not exist\n", in soc_tplg_link_config()
1749 name, cfg->id); in soc_tplg_link_config()
1750 return -EINVAL; in soc_tplg_link_config()
1754 if (cfg->num_hw_configs) in soc_tplg_link_config()
1758 if (cfg->flag_mask) in soc_tplg_link_config()
1760 le32_to_cpu(cfg->flag_mask), in soc_tplg_link_config()
1761 le32_to_cpu(cfg->flags)); in soc_tplg_link_config()
1766 dev_err(tplg->dev, "ASoC: physical link loading failed\n"); in soc_tplg_link_config()
1771 link->dobj.index = tplg->index; in soc_tplg_link_config()
1772 link->dobj.type = SND_SOC_DOBJ_BACKEND_LINK; in soc_tplg_link_config()
1773 if (tplg->ops) in soc_tplg_link_config()
1774 link->dobj.unload = tplg->ops->link_unload; in soc_tplg_link_config()
1775 list_add(&link->dobj.list, &tplg->comp->dobj_list); in soc_tplg_link_config()
1790 count = le32_to_cpu(hdr->count); in soc_tplg_link_elems_load()
1793 link = (struct snd_soc_tplg_link_config *)tplg->pos; in soc_tplg_link_elems_load()
1794 size = le32_to_cpu(link->size); in soc_tplg_link_elems_load()
1796 dev_err(tplg->dev, "ASoC: invalid size %d for physical link elems\n", in soc_tplg_link_elems_load()
1798 return -EINVAL; in soc_tplg_link_elems_load()
1802 le32_to_cpu(hdr->payload_size), in soc_tplg_link_elems_load()
1804 return -EINVAL; in soc_tplg_link_elems_load()
1808 link = (struct snd_soc_tplg_link_config *)tplg->pos; in soc_tplg_link_elems_load()
1809 size = le32_to_cpu(link->size); in soc_tplg_link_elems_load()
1811 return -EINVAL; in soc_tplg_link_elems_load()
1817 /* offset by version-specific struct size and in soc_tplg_link_elems_load()
1820 tplg->pos += size + le32_to_cpu(link->priv.size); in soc_tplg_link_elems_load()
1827 * soc_tplg_dai_config - Find and configure an existing physical DAI.
1846 dai_component.dai_name = d->dai_name; in soc_tplg_dai_config()
1849 dev_err(tplg->dev, "ASoC: physical DAI %s not registered\n", in soc_tplg_dai_config()
1850 d->dai_name); in soc_tplg_dai_config()
1851 return -EINVAL; in soc_tplg_dai_config()
1854 if (le32_to_cpu(d->dai_id) != dai->id) { in soc_tplg_dai_config()
1855 dev_err(tplg->dev, "ASoC: physical DAI %s id mismatch\n", in soc_tplg_dai_config()
1856 d->dai_name); in soc_tplg_dai_config()
1857 return -EINVAL; in soc_tplg_dai_config()
1860 dai_drv = dai->driver; in soc_tplg_dai_config()
1862 return -EINVAL; in soc_tplg_dai_config()
1864 if (d->playback) { in soc_tplg_dai_config()
1865 stream = &dai_drv->playback; in soc_tplg_dai_config()
1866 caps = &d->caps[SND_SOC_TPLG_STREAM_PLAYBACK]; in soc_tplg_dai_config()
1872 if (d->capture) { in soc_tplg_dai_config()
1873 stream = &dai_drv->capture; in soc_tplg_dai_config()
1874 caps = &d->caps[SND_SOC_TPLG_STREAM_CAPTURE]; in soc_tplg_dai_config()
1880 if (d->flag_mask) in soc_tplg_dai_config()
1882 le32_to_cpu(d->flag_mask), in soc_tplg_dai_config()
1883 le32_to_cpu(d->flags)); in soc_tplg_dai_config()
1888 dev_err(tplg->dev, "ASoC: DAI loading failed\n"); in soc_tplg_dai_config()
1902 count = le32_to_cpu(hdr->count); in soc_tplg_dai_elems_load()
1906 struct snd_soc_tplg_dai *dai = (struct snd_soc_tplg_dai *)tplg->pos; in soc_tplg_dai_elems_load()
1909 if (le32_to_cpu(dai->size) != sizeof(*dai)) { in soc_tplg_dai_elems_load()
1910 dev_err(tplg->dev, "ASoC: invalid physical DAI size\n"); in soc_tplg_dai_elems_load()
1911 return -EINVAL; in soc_tplg_dai_elems_load()
1916 dev_err(tplg->dev, "ASoC: failed to configure DAI\n"); in soc_tplg_dai_elems_load()
1920 tplg->pos += (sizeof(*dai) + le32_to_cpu(dai->priv.size)); in soc_tplg_dai_elems_load()
1923 dev_dbg(tplg->dev, "ASoC: Configure %d BE DAIs\n", count); in soc_tplg_dai_elems_load()
1933 manifest = (struct snd_soc_tplg_manifest *)tplg->pos; in soc_tplg_manifest_load()
1936 if (le32_to_cpu(manifest->size) != sizeof(*manifest)) in soc_tplg_manifest_load()
1937 return -EINVAL; in soc_tplg_manifest_load()
1940 if (tplg->ops && tplg->ops->manifest) in soc_tplg_manifest_load()
1941 ret = tplg->ops->manifest(tplg->comp, tplg->index, manifest); in soc_tplg_manifest_load()
1946 /* validate header magic, size and type */
1950 if (le32_to_cpu(hdr->size) != sizeof(*hdr)) { in soc_tplg_valid_header()
1951 dev_err(tplg->dev, in soc_tplg_valid_header()
1953 le32_to_cpu(hdr->type), soc_tplg_get_hdr_offset(tplg), in soc_tplg_valid_header()
1954 tplg->fw->size); in soc_tplg_valid_header()
1955 return -EINVAL; in soc_tplg_valid_header()
1958 if (soc_tplg_get_hdr_offset(tplg) + le32_to_cpu(hdr->payload_size) >= tplg->fw->size) { in soc_tplg_valid_header()
1959 dev_err(tplg->dev, in soc_tplg_valid_header()
1961 le32_to_cpu(hdr->type), soc_tplg_get_hdr_offset(tplg), in soc_tplg_valid_header()
1962 hdr->payload_size); in soc_tplg_valid_header()
1963 return -EINVAL; in soc_tplg_valid_header()
1967 if (le32_to_cpu(hdr->magic) == SOC_TPLG_MAGIC_BIG_ENDIAN) { in soc_tplg_valid_header()
1968 dev_err(tplg->dev, in soc_tplg_valid_header()
1970 tplg->pass, hdr->magic, in soc_tplg_valid_header()
1971 soc_tplg_get_hdr_offset(tplg), tplg->fw->size); in soc_tplg_valid_header()
1972 return -EINVAL; in soc_tplg_valid_header()
1975 if (le32_to_cpu(hdr->magic) != SND_SOC_TPLG_MAGIC) { in soc_tplg_valid_header()
1976 dev_err(tplg->dev, in soc_tplg_valid_header()
1978 tplg->pass, hdr->magic, in soc_tplg_valid_header()
1979 soc_tplg_get_hdr_offset(tplg), tplg->fw->size); in soc_tplg_valid_header()
1980 return -EINVAL; in soc_tplg_valid_header()
1984 if (le32_to_cpu(hdr->abi) > SND_SOC_TPLG_ABI_VERSION || in soc_tplg_valid_header()
1985 le32_to_cpu(hdr->abi) < SND_SOC_TPLG_ABI_VERSION_MIN) { in soc_tplg_valid_header()
1986 dev_err(tplg->dev, in soc_tplg_valid_header()
1988 tplg->pass, hdr->abi, in soc_tplg_valid_header()
1990 tplg->fw->size); in soc_tplg_valid_header()
1991 return -EINVAL; in soc_tplg_valid_header()
1994 if (hdr->payload_size == 0) { in soc_tplg_valid_header()
1995 dev_err(tplg->dev, "ASoC: header has 0 size at offset 0x%lx.\n", in soc_tplg_valid_header()
1997 return -EINVAL; in soc_tplg_valid_header()
2011 tplg->pos = tplg->hdr_pos + sizeof(struct snd_soc_tplg_hdr); in soc_tplg_load_header()
2013 tplg->index = le32_to_cpu(hdr->index); in soc_tplg_load_header()
2015 switch (le32_to_cpu(hdr->type)) { in soc_tplg_load_header()
2055 if (tplg->pass == hdr_pass) { in soc_tplg_load_header()
2056 dev_dbg(tplg->dev, in soc_tplg_load_header()
2058 hdr->payload_size, hdr->type, hdr->version, in soc_tplg_load_header()
2059 hdr->vendor_type, tplg->pass); in soc_tplg_load_header()
2072 for (tplg->pass = SOC_TPLG_PASS_START; tplg->pass <= SOC_TPLG_PASS_END; tplg->pass++) { in soc_tplg_process_headers()
2075 tplg->hdr_pos = tplg->fw->data; in soc_tplg_process_headers()
2076 hdr = (struct snd_soc_tplg_hdr *)tplg->hdr_pos; in soc_tplg_process_headers()
2088 if (ret != -EPROBE_DEFER) { in soc_tplg_process_headers()
2089 dev_err(tplg->dev, in soc_tplg_process_headers()
2097 tplg->hdr_pos += le32_to_cpu(hdr->payload_size) + in soc_tplg_process_headers()
2099 hdr = (struct snd_soc_tplg_hdr *)tplg->hdr_pos; in soc_tplg_process_headers()
2130 * comp - needs to exist to keep and reference data while parsing in snd_soc_tplg_component_load()
2131 * comp->card - used for setting card related parameters in snd_soc_tplg_component_load()
2132 * comp->card->dev - used for resource management and prints in snd_soc_tplg_component_load()
2133 * fw - we need it, as it is the very thing we parse in snd_soc_tplg_component_load()
2135 if (!comp || !comp->card || !comp->card->dev || !fw) in snd_soc_tplg_component_load()
2136 return -EINVAL; in snd_soc_tplg_component_load()
2141 tplg.dev = comp->card->dev; in snd_soc_tplg_component_load()
2145 tplg.io_ops = ops->io_ops; in snd_soc_tplg_component_load()
2146 tplg.io_ops_count = ops->io_ops_count; in snd_soc_tplg_component_load()
2147 tplg.bytes_ext_ops = ops->bytes_ext_ops; in snd_soc_tplg_component_load()
2148 tplg.bytes_ext_ops_count = ops->bytes_ext_ops_count; in snd_soc_tplg_component_load()
2167 for (pass = SOC_TPLG_PASS_END; pass >= SOC_TPLG_PASS_START; pass--) { in snd_soc_tplg_component_remove()
2170 list_for_each_entry_safe(dobj, next_dobj, &comp->dobj_list, in snd_soc_tplg_component_remove()
2173 switch (dobj->type) { in snd_soc_tplg_component_remove()
2199 dev_err(comp->dev, "ASoC: invalid component type %d for removal\n", in snd_soc_tplg_component_remove()
2200 dobj->type); in snd_soc_tplg_component_remove()
2207 return !list_empty(&comp->dobj_list); in snd_soc_tplg_component_remove()