hc
2024-02-20 102a0743326a03cd1a1202ceda21e175b7d3575c
kernel/sound/soc/soc-topology.c
....@@ -30,6 +30,8 @@
3030 #include <sound/soc-topology.h>
3131 #include <sound/tlv.h>
3232
33
+#define SOC_TPLG_MAGIC_BIG_ENDIAN 0x436F5341 /* ASoC in reverse */
34
+
3335 /*
3436 * We make several passes over the data (since it wont necessarily be ordered)
3537 * and process objects in the following order. This guarantees the component
....@@ -78,12 +80,8 @@
7880
7981 static int soc_tplg_process_headers(struct soc_tplg *tplg);
8082 static void soc_tplg_complete(struct soc_tplg *tplg);
81
-struct snd_soc_dapm_widget *
82
-snd_soc_dapm_new_control_unlocked(struct snd_soc_dapm_context *dapm,
83
- const struct snd_soc_dapm_widget *widget);
84
-struct snd_soc_dapm_widget *
85
-snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm,
86
- const struct snd_soc_dapm_widget *widget);
83
+static void soc_tplg_denum_remove_texts(struct soc_enum *se);
84
+static void soc_tplg_denum_remove_values(struct soc_enum *se);
8785
8886 /* check we dont overflow the data for this control chunk */
8987 static int soc_tplg_check_elem_count(struct soc_tplg *tplg, size_t elem_size,
....@@ -197,8 +195,8 @@
197195 int i;
198196
199197 for (i = 0; i < SND_SOC_TPLG_MAX_CHAN; i++) {
200
- if (chan[i].id == map)
201
- return chan[i].reg;
198
+ if (le32_to_cpu(chan[i].id) == map)
199
+ return le32_to_cpu(chan[i].reg);
202200 }
203201
204202 return -EINVAL;
....@@ -210,8 +208,8 @@
210208 int i;
211209
212210 for (i = 0; i < SND_SOC_TPLG_MAX_CHAN; i++) {
213
- if (chan[i].id == map)
214
- return chan[i].shift;
211
+ if (le32_to_cpu(chan[i].id) == map)
212
+ return le32_to_cpu(chan[i].shift);
215213 }
216214
217215 return -EINVAL;
....@@ -248,12 +246,12 @@
248246 }
249247
250248 /* pass vendor data to component driver for processing */
251
-static int soc_tplg_vendor_load_(struct soc_tplg *tplg,
252
- struct snd_soc_tplg_hdr *hdr)
249
+static int soc_tplg_vendor_load(struct soc_tplg *tplg,
250
+ struct snd_soc_tplg_hdr *hdr)
253251 {
254252 int ret = 0;
255253
256
- if (tplg->comp && tplg->ops && tplg->ops->vendor_load)
254
+ if (tplg->ops && tplg->ops->vendor_load)
257255 ret = tplg->ops->vendor_load(tplg->comp, tplg->index, hdr);
258256 else {
259257 dev_err(tplg->dev, "ASoC: no vendor load callback for ID %d\n",
....@@ -270,22 +268,12 @@
270268 return ret;
271269 }
272270
273
-/* pass vendor data to component driver for processing */
274
-static int soc_tplg_vendor_load(struct soc_tplg *tplg,
275
- struct snd_soc_tplg_hdr *hdr)
276
-{
277
- if (tplg->pass != SOC_TPLG_PASS_VENDOR)
278
- return 0;
279
-
280
- return soc_tplg_vendor_load_(tplg, hdr);
281
-}
282
-
283271 /* optionally pass new dynamic widget to component driver. This is mainly for
284272 * external widgets where we can assign private data/ops */
285273 static int soc_tplg_widget_load(struct soc_tplg *tplg,
286274 struct snd_soc_dapm_widget *w, struct snd_soc_tplg_dapm_widget *tplg_w)
287275 {
288
- if (tplg->comp && tplg->ops && tplg->ops->widget_load)
276
+ if (tplg->ops && tplg->ops->widget_load)
289277 return tplg->ops->widget_load(tplg->comp, tplg->index, w,
290278 tplg_w);
291279
....@@ -297,7 +285,7 @@
297285 static int soc_tplg_widget_ready(struct soc_tplg *tplg,
298286 struct snd_soc_dapm_widget *w, struct snd_soc_tplg_dapm_widget *tplg_w)
299287 {
300
- if (tplg->comp && tplg->ops && tplg->ops->widget_ready)
288
+ if (tplg->ops && tplg->ops->widget_ready)
301289 return tplg->ops->widget_ready(tplg->comp, tplg->index, w,
302290 tplg_w);
303291
....@@ -309,7 +297,7 @@
309297 struct snd_soc_dai_driver *dai_drv,
310298 struct snd_soc_tplg_pcm *pcm, struct snd_soc_dai *dai)
311299 {
312
- if (tplg->comp && tplg->ops && tplg->ops->dai_load)
300
+ if (tplg->ops && tplg->ops->dai_load)
313301 return tplg->ops->dai_load(tplg->comp, tplg->index, dai_drv,
314302 pcm, dai);
315303
....@@ -320,7 +308,7 @@
320308 static int soc_tplg_dai_link_load(struct soc_tplg *tplg,
321309 struct snd_soc_dai_link *link, struct snd_soc_tplg_link_config *cfg)
322310 {
323
- if (tplg->comp && tplg->ops && tplg->ops->link_load)
311
+ if (tplg->ops && tplg->ops->link_load)
324312 return tplg->ops->link_load(tplg->comp, tplg->index, link, cfg);
325313
326314 return 0;
....@@ -329,7 +317,7 @@
329317 /* tell the component driver that all firmware has been loaded in this request */
330318 static void soc_tplg_complete(struct soc_tplg *tplg)
331319 {
332
- if (tplg->comp && tplg->ops && tplg->ops->complete)
320
+ if (tplg->ops && tplg->ops->complete)
333321 tplg->ops->complete(tplg->comp);
334322 }
335323
....@@ -382,10 +370,10 @@
382370 if (dobj->ops && dobj->ops->control_unload)
383371 dobj->ops->control_unload(comp, dobj);
384372
385
- if (sm->dobj.control.kcontrol->tlv.p)
386
- p = sm->dobj.control.kcontrol->tlv.p;
387
- snd_ctl_remove(card, sm->dobj.control.kcontrol);
388
- list_del(&sm->dobj.list);
373
+ if (dobj->control.kcontrol->tlv.p)
374
+ p = dobj->control.kcontrol->tlv.p;
375
+ snd_ctl_remove(card, dobj->control.kcontrol);
376
+ list_del(&dobj->list);
389377 kfree(sm);
390378 kfree(p);
391379 }
....@@ -396,7 +384,6 @@
396384 {
397385 struct snd_card *card = comp->card->snd_card;
398386 struct soc_enum *se = container_of(dobj, struct soc_enum, dobj);
399
- int i;
400387
401388 if (pass != SOC_TPLG_PASS_MIXER)
402389 return;
....@@ -404,12 +391,11 @@
404391 if (dobj->ops && dobj->ops->control_unload)
405392 dobj->ops->control_unload(comp, dobj);
406393
407
- snd_ctl_remove(card, se->dobj.control.kcontrol);
408
- list_del(&se->dobj.list);
394
+ snd_ctl_remove(card, dobj->control.kcontrol);
395
+ list_del(&dobj->list);
409396
410
- kfree(se->dobj.control.dvalues);
411
- for (i = 0; i < se->items; i++)
412
- kfree(se->dobj.control.dtexts[i]);
397
+ soc_tplg_denum_remove_values(se);
398
+ soc_tplg_denum_remove_texts(se);
413399 kfree(se);
414400 }
415401
....@@ -427,9 +413,26 @@
427413 if (dobj->ops && dobj->ops->control_unload)
428414 dobj->ops->control_unload(comp, dobj);
429415
430
- snd_ctl_remove(card, sb->dobj.control.kcontrol);
431
- list_del(&sb->dobj.list);
416
+ snd_ctl_remove(card, dobj->control.kcontrol);
417
+ list_del(&dobj->list);
432418 kfree(sb);
419
+}
420
+
421
+/* remove a route */
422
+static void remove_route(struct snd_soc_component *comp,
423
+ struct snd_soc_dobj *dobj, int pass)
424
+{
425
+ struct snd_soc_dapm_route *route =
426
+ container_of(dobj, struct snd_soc_dapm_route, dobj);
427
+
428
+ if (pass != SOC_TPLG_PASS_GRAPH)
429
+ return;
430
+
431
+ if (dobj->ops && dobj->ops->dapm_route_unload)
432
+ dobj->ops->dapm_route_unload(comp, dobj);
433
+
434
+ list_del(&dobj->list);
435
+ kfree(route);
433436 }
434437
435438 /* remove a widget and it's kcontrols - routes must be removed first */
....@@ -460,13 +463,12 @@
460463 struct snd_kcontrol *kcontrol = w->kcontrols[i];
461464 struct soc_enum *se =
462465 (struct soc_enum *)kcontrol->private_value;
463
- int j;
464466
465467 snd_ctl_remove(card, kcontrol);
466468
467
- kfree(se->dobj.control.dvalues);
468
- for (j = 0; j < se->items; j++)
469
- kfree(se->dobj.control.dtexts[j]);
469
+ /* free enum kcontrol's dvalues and dtexts */
470
+ soc_tplg_denum_remove_values(se);
471
+ soc_tplg_denum_remove_texts(se);
470472
471473 kfree(se);
472474 kfree(w->kcontrol_news[i].name);
....@@ -493,6 +495,8 @@
493495 free_news:
494496 kfree(w->kcontrol_news);
495497
498
+ list_del(&dobj->list);
499
+
496500 /* widget w is freed by soc-dapm.c */
497501 }
498502
....@@ -502,6 +506,7 @@
502506 {
503507 struct snd_soc_dai_driver *dai_drv =
504508 container_of(dobj, struct snd_soc_dai_driver, dobj);
509
+ struct snd_soc_dai *dai, *_dai;
505510
506511 if (pass != SOC_TPLG_PASS_PCM_DAI)
507512 return;
....@@ -509,6 +514,12 @@
509514 if (dobj->ops && dobj->ops->dai_unload)
510515 dobj->ops->dai_unload(comp, dobj);
511516
517
+ for_each_component_dais_safe(comp, dai, _dai)
518
+ if (dai->driver == dai_drv)
519
+ snd_soc_unregister_dai(dai);
520
+
521
+ kfree(dai_drv->playback.stream_name);
522
+ kfree(dai_drv->capture.stream_name);
512523 kfree(dai_drv->name);
513524 list_del(&dobj->list);
514525 kfree(dai_drv);
....@@ -527,13 +538,33 @@
527538 if (dobj->ops && dobj->ops->link_unload)
528539 dobj->ops->link_unload(comp, dobj);
529540
541
+ list_del(&dobj->list);
542
+ snd_soc_remove_pcm_runtime(comp->card,
543
+ snd_soc_get_pcm_runtime(comp->card, link));
544
+
530545 kfree(link->name);
531546 kfree(link->stream_name);
532
- kfree(link->cpu_dai_name);
533
-
534
- list_del(&dobj->list);
535
- snd_soc_remove_dai_link(comp->card, link);
547
+ kfree(link->cpus->dai_name);
536548 kfree(link);
549
+}
550
+
551
+/* unload dai link */
552
+static void remove_backend_link(struct snd_soc_component *comp,
553
+ struct snd_soc_dobj *dobj, int pass)
554
+{
555
+ if (pass != SOC_TPLG_PASS_LINK)
556
+ return;
557
+
558
+ if (dobj->ops && dobj->ops->link_unload)
559
+ dobj->ops->link_unload(comp, dobj);
560
+
561
+ /*
562
+ * We don't free the link here as what remove_link() do since BE
563
+ * links are not allocated by topology.
564
+ * We however need to reset the dobj type to its initial values
565
+ */
566
+ dobj->type = SND_SOC_DOBJ_NONE;
567
+ list_del(&dobj->list);
537568 }
538569
539570 /* bind a kcontrol to it's IO handlers */
....@@ -545,9 +576,10 @@
545576 const struct snd_soc_tplg_bytes_ext_ops *ext_ops;
546577 int num_ops, i;
547578
548
- if (hdr->ops.info == SND_SOC_TPLG_CTL_BYTES
579
+ if (le32_to_cpu(hdr->ops.info) == SND_SOC_TPLG_CTL_BYTES
549580 && k->iface & SNDRV_CTL_ELEM_IFACE_MIXER
550
- && k->access & SNDRV_CTL_ELEM_ACCESS_TLV_READWRITE
581
+ && (k->access & SNDRV_CTL_ELEM_ACCESS_TLV_READ
582
+ || k->access & SNDRV_CTL_ELEM_ACCESS_TLV_WRITE)
551583 && k->access & SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK) {
552584 struct soc_bytes_ext *sbe;
553585 struct snd_soc_tplg_bytes_control *be;
....@@ -561,19 +593,33 @@
561593 k->info = snd_soc_bytes_info_ext;
562594 k->tlv.c = snd_soc_bytes_tlv_callback;
563595
596
+ /*
597
+ * When a topology-based implementation abuses the
598
+ * control interface and uses bytes_ext controls of
599
+ * more than 512 bytes, we need to disable the size
600
+ * checks, otherwise accesses to such controls will
601
+ * return an -EINVAL error and prevent the card from
602
+ * being configured.
603
+ */
604
+ if (IS_ENABLED(CONFIG_SND_CTL_VALIDATION) && sbe->max > 512)
605
+ k->access |= SNDRV_CTL_ELEM_ACCESS_SKIP_CHECK;
606
+
564607 ext_ops = tplg->bytes_ext_ops;
565608 num_ops = tplg->bytes_ext_ops_count;
566609 for (i = 0; i < num_ops; i++) {
567
- if (!sbe->put && ext_ops[i].id == be->ext_ops.put)
610
+ if (!sbe->put &&
611
+ ext_ops[i].id == le32_to_cpu(be->ext_ops.put))
568612 sbe->put = ext_ops[i].put;
569
- if (!sbe->get && ext_ops[i].id == be->ext_ops.get)
613
+ if (!sbe->get &&
614
+ ext_ops[i].id == le32_to_cpu(be->ext_ops.get))
570615 sbe->get = ext_ops[i].get;
571616 }
572617
573
- if (sbe->put && sbe->get)
574
- return 0;
575
- else
618
+ if ((k->access & SNDRV_CTL_ELEM_ACCESS_TLV_READ) && !sbe->get)
576619 return -EINVAL;
620
+ if ((k->access & SNDRV_CTL_ELEM_ACCESS_TLV_WRITE) && !sbe->put)
621
+ return -EINVAL;
622
+ return 0;
577623 }
578624
579625 /* try and map vendor specific kcontrol handlers first */
....@@ -581,11 +627,11 @@
581627 num_ops = tplg->io_ops_count;
582628 for (i = 0; i < num_ops; i++) {
583629
584
- if (k->put == NULL && ops[i].id == hdr->ops.put)
630
+ if (k->put == NULL && ops[i].id == le32_to_cpu(hdr->ops.put))
585631 k->put = ops[i].put;
586
- if (k->get == NULL && ops[i].id == hdr->ops.get)
632
+ if (k->get == NULL && ops[i].id == le32_to_cpu(hdr->ops.get))
587633 k->get = ops[i].get;
588
- if (k->info == NULL && ops[i].id == hdr->ops.info)
634
+ if (k->info == NULL && ops[i].id == le32_to_cpu(hdr->ops.info))
589635 k->info = ops[i].info;
590636 }
591637
....@@ -598,11 +644,11 @@
598644 num_ops = ARRAY_SIZE(io_ops);
599645 for (i = 0; i < num_ops; i++) {
600646
601
- if (k->put == NULL && ops[i].id == hdr->ops.put)
647
+ if (k->put == NULL && ops[i].id == le32_to_cpu(hdr->ops.put))
602648 k->put = ops[i].put;
603
- if (k->get == NULL && ops[i].id == hdr->ops.get)
649
+ if (k->get == NULL && ops[i].id == le32_to_cpu(hdr->ops.get))
604650 k->get = ops[i].get;
605
- if (k->info == NULL && ops[i].id == hdr->ops.info)
651
+ if (k->info == NULL && ops[i].id == le32_to_cpu(hdr->ops.info))
606652 k->info = ops[i].info;
607653 }
608654
....@@ -641,7 +687,7 @@
641687 static int soc_tplg_init_kcontrol(struct soc_tplg *tplg,
642688 struct snd_kcontrol_new *k, struct snd_soc_tplg_ctl_hdr *hdr)
643689 {
644
- if (tplg->comp && tplg->ops && tplg->ops->control_load)
690
+ if (tplg->ops && tplg->ops->control_load)
645691 return tplg->ops->control_load(tplg->comp, tplg->index, k,
646692 hdr);
647693
....@@ -661,9 +707,9 @@
661707
662708 p[0] = SNDRV_CTL_TLVT_DB_SCALE;
663709 p[1] = item_len;
664
- p[2] = scale->min;
665
- p[3] = (scale->step & TLV_DB_SCALE_MASK)
666
- | (scale->mute ? TLV_DB_SCALE_MUTE : 0);
710
+ p[2] = le32_to_cpu(scale->min);
711
+ p[3] = (le32_to_cpu(scale->step) & TLV_DB_SCALE_MASK)
712
+ | (le32_to_cpu(scale->mute) ? TLV_DB_SCALE_MUTE : 0);
667713
668714 kc->tlv.p = (void *)p;
669715 return 0;
....@@ -673,13 +719,14 @@
673719 struct snd_kcontrol_new *kc, struct snd_soc_tplg_ctl_hdr *tc)
674720 {
675721 struct snd_soc_tplg_ctl_tlv *tplg_tlv;
722
+ u32 access = le32_to_cpu(tc->access);
676723
677
- if (!(tc->access & SNDRV_CTL_ELEM_ACCESS_TLV_READWRITE))
724
+ if (!(access & SNDRV_CTL_ELEM_ACCESS_TLV_READWRITE))
678725 return 0;
679726
680
- if (!(tc->access & SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK)) {
727
+ if (!(access & SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK)) {
681728 tplg_tlv = &tc->tlv;
682
- switch (tplg_tlv->type) {
729
+ switch (le32_to_cpu(tplg_tlv->type)) {
683730 case SNDRV_CTL_TLVT_DB_SCALE:
684731 return soc_tplg_create_tlv_db_scale(tplg, kc,
685732 &tplg_tlv->scale);
....@@ -707,7 +754,8 @@
707754 struct snd_soc_tplg_bytes_control *be;
708755 struct soc_bytes_ext *sbe;
709756 struct snd_kcontrol_new kc;
710
- int i, err;
757
+ int i;
758
+ int err = 0;
711759
712760 if (soc_tplg_check_elem_count(tplg,
713761 sizeof(struct snd_soc_tplg_bytes_control), count,
....@@ -730,7 +778,7 @@
730778 return -ENOMEM;
731779
732780 tplg->pos += (sizeof(struct snd_soc_tplg_bytes_control) +
733
- be->priv.size);
781
+ le32_to_cpu(be->priv.size));
734782
735783 dev_dbg(tplg->dev,
736784 "ASoC: adding bytes kcontrol %s with access 0x%x\n",
....@@ -740,9 +788,9 @@
740788 kc.name = be->hdr.name;
741789 kc.private_value = (long)sbe;
742790 kc.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
743
- kc.access = be->hdr.access;
791
+ kc.access = le32_to_cpu(be->hdr.access);
744792
745
- sbe->max = be->max;
793
+ sbe->max = le32_to_cpu(be->max);
746794 sbe->dobj.type = SND_SOC_DOBJ_BYTES;
747795 sbe->dobj.ops = tplg->ops;
748796 INIT_LIST_HEAD(&sbe->dobj.list);
....@@ -752,7 +800,7 @@
752800 if (err) {
753801 soc_control_err(tplg, &be->hdr, be->hdr.name);
754802 kfree(sbe);
755
- continue;
803
+ break;
756804 }
757805
758806 /* pass control to driver for optional further init */
....@@ -762,7 +810,7 @@
762810 dev_err(tplg->dev, "ASoC: failed to init %s\n",
763811 be->hdr.name);
764812 kfree(sbe);
765
- continue;
813
+ break;
766814 }
767815
768816 /* register control here */
....@@ -772,12 +820,12 @@
772820 dev_err(tplg->dev, "ASoC: failed to add %s\n",
773821 be->hdr.name);
774822 kfree(sbe);
775
- continue;
823
+ break;
776824 }
777825
778826 list_add(&sbe->dobj.list, &tplg->comp->dobj_list);
779827 }
780
- return 0;
828
+ return err;
781829
782830 }
783831
....@@ -787,7 +835,8 @@
787835 struct snd_soc_tplg_mixer_control *mc;
788836 struct soc_mixer_control *sm;
789837 struct snd_kcontrol_new kc;
790
- int i, err;
838
+ int i;
839
+ int err = 0;
791840
792841 if (soc_tplg_check_elem_count(tplg,
793842 sizeof(struct snd_soc_tplg_mixer_control),
....@@ -810,7 +859,7 @@
810859 if (sm == NULL)
811860 return -ENOMEM;
812861 tplg->pos += (sizeof(struct snd_soc_tplg_mixer_control) +
813
- mc->priv.size);
862
+ le32_to_cpu(mc->priv.size));
814863
815864 dev_dbg(tplg->dev,
816865 "ASoC: adding mixer kcontrol %s with access 0x%x\n",
....@@ -820,7 +869,7 @@
820869 kc.name = mc->hdr.name;
821870 kc.private_value = (long)sm;
822871 kc.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
823
- kc.access = mc->hdr.access;
872
+ kc.access = le32_to_cpu(mc->hdr.access);
824873
825874 /* we only support FL/FR channel mapping atm */
826875 sm->reg = tplc_chan_get_reg(tplg, mc->channel,
....@@ -832,10 +881,10 @@
832881 sm->rshift = tplc_chan_get_shift(tplg, mc->channel,
833882 SNDRV_CHMAP_FR);
834883
835
- sm->max = mc->max;
836
- sm->min = mc->min;
837
- sm->invert = mc->invert;
838
- sm->platform_max = mc->platform_max;
884
+ sm->max = le32_to_cpu(mc->max);
885
+ sm->min = le32_to_cpu(mc->min);
886
+ sm->invert = le32_to_cpu(mc->invert);
887
+ sm->platform_max = le32_to_cpu(mc->platform_max);
839888 sm->dobj.index = tplg->index;
840889 sm->dobj.ops = tplg->ops;
841890 sm->dobj.type = SND_SOC_DOBJ_MIXER;
....@@ -846,7 +895,16 @@
846895 if (err) {
847896 soc_control_err(tplg, &mc->hdr, mc->hdr.name);
848897 kfree(sm);
849
- continue;
898
+ break;
899
+ }
900
+
901
+ /* create any TLV data */
902
+ err = soc_tplg_create_tlv(tplg, &kc, &mc->hdr);
903
+ if (err < 0) {
904
+ dev_err(tplg->dev, "ASoC: failed to create TLV %s\n",
905
+ mc->hdr.name);
906
+ kfree(sm);
907
+ break;
850908 }
851909
852910 /* pass control to driver for optional further init */
....@@ -855,12 +913,10 @@
855913 if (err < 0) {
856914 dev_err(tplg->dev, "ASoC: failed to init %s\n",
857915 mc->hdr.name);
916
+ soc_tplg_free_tlv(tplg, &kc);
858917 kfree(sm);
859
- continue;
918
+ break;
860919 }
861
-
862
- /* create any TLV data */
863
- soc_tplg_create_tlv(tplg, &kc, &mc->hdr);
864920
865921 /* register control here */
866922 err = soc_tplg_add_kcontrol(tplg, &kc,
....@@ -870,13 +926,13 @@
870926 mc->hdr.name);
871927 soc_tplg_free_tlv(tplg, &kc);
872928 kfree(sm);
873
- continue;
929
+ break;
874930 }
875931
876932 list_add(&sm->dobj.list, &tplg->comp->dobj_list);
877933 }
878934
879
- return 0;
935
+ return err;
880936 }
881937
882938 static int soc_tplg_denum_create_texts(struct soc_enum *se,
....@@ -885,11 +941,11 @@
885941 int i, ret;
886942
887943 se->dobj.control.dtexts =
888
- kcalloc(ec->items, sizeof(char *), GFP_KERNEL);
944
+ kcalloc(le32_to_cpu(ec->items), sizeof(char *), GFP_KERNEL);
889945 if (se->dobj.control.dtexts == NULL)
890946 return -ENOMEM;
891947
892
- for (i = 0; i < ec->items; i++) {
948
+ for (i = 0; i < le32_to_cpu(ec->items); i++) {
893949
894950 if (strnlen(ec->texts[i], SNDRV_CTL_ELEM_ID_NAME_MAXLEN) ==
895951 SNDRV_CTL_ELEM_ID_NAME_MAXLEN) {
....@@ -904,29 +960,50 @@
904960 }
905961 }
906962
963
+ se->items = le32_to_cpu(ec->items);
907964 se->texts = (const char * const *)se->dobj.control.dtexts;
908965 return 0;
909966
910967 err:
968
+ se->items = i;
969
+ soc_tplg_denum_remove_texts(se);
970
+ return ret;
971
+}
972
+
973
+static inline void soc_tplg_denum_remove_texts(struct soc_enum *se)
974
+{
975
+ int i = se->items;
976
+
911977 for (--i; i >= 0; i--)
912978 kfree(se->dobj.control.dtexts[i]);
913979 kfree(se->dobj.control.dtexts);
914
- return ret;
915980 }
916981
917982 static int soc_tplg_denum_create_values(struct soc_enum *se,
918983 struct snd_soc_tplg_enum_control *ec)
919984 {
920
- if (ec->items > sizeof(*ec->values))
985
+ int i;
986
+
987
+ if (le32_to_cpu(ec->items) > sizeof(*ec->values))
921988 return -EINVAL;
922989
923
- se->dobj.control.dvalues = kmemdup(ec->values,
924
- ec->items * sizeof(u32),
990
+ se->dobj.control.dvalues = kzalloc(le32_to_cpu(ec->items) *
991
+ sizeof(*se->dobj.control.dvalues),
925992 GFP_KERNEL);
926993 if (!se->dobj.control.dvalues)
927994 return -ENOMEM;
928995
996
+ /* convert from little-endian */
997
+ for (i = 0; i < le32_to_cpu(ec->items); i++) {
998
+ se->dobj.control.dvalues[i] = le32_to_cpu(ec->values[i]);
999
+ }
1000
+
9291001 return 0;
1002
+}
1003
+
1004
+static inline void soc_tplg_denum_remove_values(struct soc_enum *se)
1005
+{
1006
+ kfree(se->dobj.control.dvalues);
9301007 }
9311008
9321009 static int soc_tplg_denum_create(struct soc_tplg *tplg, unsigned int count,
....@@ -935,7 +1012,8 @@
9351012 struct snd_soc_tplg_enum_control *ec;
9361013 struct soc_enum *se;
9371014 struct snd_kcontrol_new kc;
938
- int i, ret, err;
1015
+ int i;
1016
+ int err = 0;
9391017
9401018 if (soc_tplg_check_elem_count(tplg,
9411019 sizeof(struct snd_soc_tplg_enum_control),
....@@ -948,8 +1026,6 @@
9481026
9491027 for (i = 0; i < count; i++) {
9501028 ec = (struct snd_soc_tplg_enum_control *)tplg->pos;
951
- tplg->pos += (sizeof(struct snd_soc_tplg_enum_control) +
952
- ec->priv.size);
9531029
9541030 /* validate kcontrol */
9551031 if (strnlen(ec->hdr.name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN) ==
....@@ -960,6 +1036,9 @@
9601036 if (se == NULL)
9611037 return -ENOMEM;
9621038
1039
+ tplg->pos += (sizeof(struct snd_soc_tplg_enum_control) +
1040
+ le32_to_cpu(ec->priv.size));
1041
+
9631042 dev_dbg(tplg->dev, "ASoC: adding enum kcontrol %s size %d\n",
9641043 ec->hdr.name, ec->items);
9651044
....@@ -967,7 +1046,7 @@
9671046 kc.name = ec->hdr.name;
9681047 kc.private_value = (long)se;
9691048 kc.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
970
- kc.access = ec->hdr.access;
1049
+ kc.access = le32_to_cpu(ec->hdr.access);
9711050
9721051 se->reg = tplc_chan_get_reg(tplg, ec->channel, SNDRV_CHMAP_FL);
9731052 se->shift_l = tplc_chan_get_shift(tplg, ec->channel,
....@@ -975,14 +1054,13 @@
9751054 se->shift_r = tplc_chan_get_shift(tplg, ec->channel,
9761055 SNDRV_CHMAP_FL);
9771056
978
- se->items = ec->items;
979
- se->mask = ec->mask;
1057
+ se->mask = le32_to_cpu(ec->mask);
9801058 se->dobj.index = tplg->index;
9811059 se->dobj.type = SND_SOC_DOBJ_ENUM;
9821060 se->dobj.ops = tplg->ops;
9831061 INIT_LIST_HEAD(&se->dobj.list);
9841062
985
- switch (ec->hdr.ops.info) {
1063
+ switch (le32_to_cpu(ec->hdr.ops.info)) {
9861064 case SND_SOC_TPLG_DAPM_CTL_ENUM_VALUE:
9871065 case SND_SOC_TPLG_CTL_ENUM_VALUE:
9881066 err = soc_tplg_denum_create_values(se, ec);
....@@ -990,10 +1068,9 @@
9901068 dev_err(tplg->dev,
9911069 "ASoC: could not create values for %s\n",
9921070 ec->hdr.name);
993
- kfree(se);
994
- continue;
1071
+ goto err_denum;
9951072 }
996
- /* fall through and create texts */
1073
+ fallthrough;
9971074 case SND_SOC_TPLG_CTL_ENUM:
9981075 case SND_SOC_TPLG_DAPM_CTL_ENUM_DOUBLE:
9991076 case SND_SOC_TPLG_DAPM_CTL_ENUM_VIRT:
....@@ -1002,24 +1079,22 @@
10021079 dev_err(tplg->dev,
10031080 "ASoC: could not create texts for %s\n",
10041081 ec->hdr.name);
1005
- kfree(se);
1006
- continue;
1082
+ goto err_denum;
10071083 }
10081084 break;
10091085 default:
1086
+ err = -EINVAL;
10101087 dev_err(tplg->dev,
10111088 "ASoC: invalid enum control type %d for %s\n",
10121089 ec->hdr.ops.info, ec->hdr.name);
1013
- kfree(se);
1014
- continue;
1090
+ goto err_denum;
10151091 }
10161092
10171093 /* map io handlers */
10181094 err = soc_tplg_kcontrol_bind_io(&ec->hdr, &kc, tplg);
10191095 if (err) {
10201096 soc_control_err(tplg, &ec->hdr, ec->hdr.name);
1021
- kfree(se);
1022
- continue;
1097
+ goto err_denum;
10231098 }
10241099
10251100 /* pass control to driver for optional further init */
....@@ -1028,50 +1103,47 @@
10281103 if (err < 0) {
10291104 dev_err(tplg->dev, "ASoC: failed to init %s\n",
10301105 ec->hdr.name);
1031
- kfree(se);
1032
- continue;
1106
+ goto err_denum;
10331107 }
10341108
10351109 /* register control here */
1036
- ret = soc_tplg_add_kcontrol(tplg,
1037
- &kc, &se->dobj.control.kcontrol);
1038
- if (ret < 0) {
1110
+ err = soc_tplg_add_kcontrol(tplg,
1111
+ &kc, &se->dobj.control.kcontrol);
1112
+ if (err < 0) {
10391113 dev_err(tplg->dev, "ASoC: could not add kcontrol %s\n",
10401114 ec->hdr.name);
1041
- kfree(se);
1042
- continue;
1115
+ goto err_denum;
10431116 }
10441117
10451118 list_add(&se->dobj.list, &tplg->comp->dobj_list);
10461119 }
1047
-
10481120 return 0;
1121
+
1122
+err_denum:
1123
+ kfree(se);
1124
+ return err;
10491125 }
10501126
10511127 static int soc_tplg_kcontrol_elems_load(struct soc_tplg *tplg,
10521128 struct snd_soc_tplg_hdr *hdr)
10531129 {
10541130 struct snd_soc_tplg_ctl_hdr *control_hdr;
1131
+ int ret;
10551132 int i;
1056
-
1057
- if (tplg->pass != SOC_TPLG_PASS_MIXER) {
1058
- tplg->pos += hdr->size + hdr->payload_size;
1059
- return 0;
1060
- }
10611133
10621134 dev_dbg(tplg->dev, "ASoC: adding %d kcontrols at 0x%lx\n", hdr->count,
10631135 soc_tplg_get_offset(tplg));
10641136
1065
- for (i = 0; i < hdr->count; i++) {
1137
+ for (i = 0; i < le32_to_cpu(hdr->count); i++) {
10661138
10671139 control_hdr = (struct snd_soc_tplg_ctl_hdr *)tplg->pos;
10681140
1069
- if (control_hdr->size != sizeof(*control_hdr)) {
1141
+ if (le32_to_cpu(control_hdr->size) != sizeof(*control_hdr)) {
10701142 dev_err(tplg->dev, "ASoC: invalid control size\n");
10711143 return -EINVAL;
10721144 }
10731145
1074
- switch (control_hdr->ops.info) {
1146
+ switch (le32_to_cpu(control_hdr->ops.info)) {
10751147 case SND_SOC_TPLG_CTL_VOLSW:
10761148 case SND_SOC_TPLG_CTL_STROBE:
10771149 case SND_SOC_TPLG_CTL_VOLSW_SX:
....@@ -1079,22 +1151,30 @@
10791151 case SND_SOC_TPLG_CTL_RANGE:
10801152 case SND_SOC_TPLG_DAPM_CTL_VOLSW:
10811153 case SND_SOC_TPLG_DAPM_CTL_PIN:
1082
- soc_tplg_dmixer_create(tplg, 1, hdr->payload_size);
1154
+ ret = soc_tplg_dmixer_create(tplg, 1,
1155
+ le32_to_cpu(hdr->payload_size));
10831156 break;
10841157 case SND_SOC_TPLG_CTL_ENUM:
10851158 case SND_SOC_TPLG_CTL_ENUM_VALUE:
10861159 case SND_SOC_TPLG_DAPM_CTL_ENUM_DOUBLE:
10871160 case SND_SOC_TPLG_DAPM_CTL_ENUM_VIRT:
10881161 case SND_SOC_TPLG_DAPM_CTL_ENUM_VALUE:
1089
- soc_tplg_denum_create(tplg, 1, hdr->payload_size);
1162
+ ret = soc_tplg_denum_create(tplg, 1,
1163
+ le32_to_cpu(hdr->payload_size));
10901164 break;
10911165 case SND_SOC_TPLG_CTL_BYTES:
1092
- soc_tplg_dbytes_create(tplg, 1, hdr->payload_size);
1166
+ ret = soc_tplg_dbytes_create(tplg, 1,
1167
+ le32_to_cpu(hdr->payload_size));
10931168 break;
10941169 default:
10951170 soc_bind_err(tplg, control_hdr, i);
10961171 return -EINVAL;
10971172 }
1173
+ if (ret < 0) {
1174
+ dev_err(tplg->dev, "ASoC: invalid control\n");
1175
+ return ret;
1176
+ }
1177
+
10981178 }
10991179
11001180 return 0;
....@@ -1104,7 +1184,7 @@
11041184 static int soc_tplg_add_route(struct soc_tplg *tplg,
11051185 struct snd_soc_dapm_route *route)
11061186 {
1107
- if (tplg->comp && tplg->ops && tplg->ops->dapm_route_load)
1187
+ if (tplg->ops && tplg->ops->dapm_route_load)
11081188 return tplg->ops->dapm_route_load(tplg->comp, tplg->index,
11091189 route);
11101190
....@@ -1115,18 +1195,16 @@
11151195 struct snd_soc_tplg_hdr *hdr)
11161196 {
11171197 struct snd_soc_dapm_context *dapm = &tplg->comp->dapm;
1118
- struct snd_soc_dapm_route route;
11191198 struct snd_soc_tplg_dapm_graph_elem *elem;
1120
- int count = hdr->count, i;
1199
+ struct snd_soc_dapm_route **routes;
1200
+ int count, i, j;
1201
+ int ret = 0;
11211202
1122
- if (tplg->pass != SOC_TPLG_PASS_GRAPH) {
1123
- tplg->pos += hdr->size + hdr->payload_size;
1124
- return 0;
1125
- }
1203
+ count = le32_to_cpu(hdr->count);
11261204
11271205 if (soc_tplg_check_elem_count(tplg,
11281206 sizeof(struct snd_soc_tplg_dapm_graph_elem),
1129
- count, hdr->payload_size, "graph")) {
1207
+ count, le32_to_cpu(hdr->payload_size), "graph")) {
11301208
11311209 dev_err(tplg->dev, "ASoC: invalid count %d for DAPM routes\n",
11321210 count);
....@@ -1136,36 +1214,100 @@
11361214 dev_dbg(tplg->dev, "ASoC: adding %d DAPM routes for index %d\n", count,
11371215 hdr->index);
11381216
1217
+ /* allocate memory for pointer to array of dapm routes */
1218
+ routes = kcalloc(count, sizeof(struct snd_soc_dapm_route *),
1219
+ GFP_KERNEL);
1220
+ if (!routes)
1221
+ return -ENOMEM;
1222
+
1223
+ /*
1224
+ * allocate memory for each dapm route in the array.
1225
+ * This needs to be done individually so that
1226
+ * each route can be freed when it is removed in remove_route().
1227
+ */
1228
+ for (i = 0; i < count; i++) {
1229
+ routes[i] = kzalloc(sizeof(*routes[i]), GFP_KERNEL);
1230
+ if (!routes[i]) {
1231
+ /* free previously allocated memory */
1232
+ for (j = 0; j < i; j++)
1233
+ kfree(routes[j]);
1234
+
1235
+ kfree(routes);
1236
+ return -ENOMEM;
1237
+ }
1238
+ }
1239
+
11391240 for (i = 0; i < count; i++) {
11401241 elem = (struct snd_soc_tplg_dapm_graph_elem *)tplg->pos;
11411242 tplg->pos += sizeof(struct snd_soc_tplg_dapm_graph_elem);
11421243
11431244 /* validate routes */
11441245 if (strnlen(elem->source, SNDRV_CTL_ELEM_ID_NAME_MAXLEN) ==
1145
- SNDRV_CTL_ELEM_ID_NAME_MAXLEN)
1146
- return -EINVAL;
1246
+ SNDRV_CTL_ELEM_ID_NAME_MAXLEN) {
1247
+ ret = -EINVAL;
1248
+ break;
1249
+ }
11471250 if (strnlen(elem->sink, SNDRV_CTL_ELEM_ID_NAME_MAXLEN) ==
1148
- SNDRV_CTL_ELEM_ID_NAME_MAXLEN)
1149
- return -EINVAL;
1251
+ SNDRV_CTL_ELEM_ID_NAME_MAXLEN) {
1252
+ ret = -EINVAL;
1253
+ break;
1254
+ }
11501255 if (strnlen(elem->control, SNDRV_CTL_ELEM_ID_NAME_MAXLEN) ==
1151
- SNDRV_CTL_ELEM_ID_NAME_MAXLEN)
1152
- return -EINVAL;
1256
+ SNDRV_CTL_ELEM_ID_NAME_MAXLEN) {
1257
+ ret = -EINVAL;
1258
+ break;
1259
+ }
11531260
1154
- route.source = elem->source;
1155
- route.sink = elem->sink;
1156
- route.connected = NULL; /* set to NULL atm for tplg users */
1261
+ routes[i]->source = elem->source;
1262
+ routes[i]->sink = elem->sink;
1263
+
1264
+ /* set to NULL atm for tplg users */
1265
+ routes[i]->connected = NULL;
11571266 if (strnlen(elem->control, SNDRV_CTL_ELEM_ID_NAME_MAXLEN) == 0)
1158
- route.control = NULL;
1267
+ routes[i]->control = NULL;
11591268 else
1160
- route.control = elem->control;
1269
+ routes[i]->control = elem->control;
11611270
1162
- soc_tplg_add_route(tplg, &route);
1271
+ /* add route dobj to dobj_list */
1272
+ routes[i]->dobj.type = SND_SOC_DOBJ_GRAPH;
1273
+ routes[i]->dobj.ops = tplg->ops;
1274
+ routes[i]->dobj.index = tplg->index;
1275
+ list_add(&routes[i]->dobj.list, &tplg->comp->dobj_list);
1276
+
1277
+ ret = soc_tplg_add_route(tplg, routes[i]);
1278
+ if (ret < 0) {
1279
+ dev_err(tplg->dev, "ASoC: topology: add_route failed: %d\n", ret);
1280
+ /*
1281
+ * this route was added to the list, it will
1282
+ * be freed in remove_route() so increment the
1283
+ * counter to skip it in the error handling
1284
+ * below.
1285
+ */
1286
+ i++;
1287
+ break;
1288
+ }
11631289
11641290 /* add route, but keep going if some fail */
1165
- snd_soc_dapm_add_routes(dapm, &route, 1);
1291
+ snd_soc_dapm_add_routes(dapm, routes[i], 1);
11661292 }
11671293
1168
- return 0;
1294
+ /*
1295
+ * free memory allocated for all dapm routes not added to the
1296
+ * list in case of error
1297
+ */
1298
+ if (ret < 0) {
1299
+ while (i < count)
1300
+ kfree(routes[i++]);
1301
+ }
1302
+
1303
+ /*
1304
+ * free pointer to array of dapm routes as this is no longer needed.
1305
+ * The memory allocated for each dapm route will be freed
1306
+ * when it is removed in remove_route().
1307
+ */
1308
+ kfree(routes);
1309
+
1310
+ return ret;
11691311 }
11701312
11711313 static struct snd_kcontrol_new *soc_tplg_dapm_widget_dmixer_create(
....@@ -1182,27 +1324,28 @@
11821324
11831325 for (i = 0; i < num_kcontrols; i++) {
11841326 mc = (struct snd_soc_tplg_mixer_control *)tplg->pos;
1185
- sm = kzalloc(sizeof(*sm), GFP_KERNEL);
1186
- if (sm == NULL)
1187
- goto err;
1188
-
1189
- tplg->pos += (sizeof(struct snd_soc_tplg_mixer_control) +
1190
- mc->priv.size);
11911327
11921328 /* validate kcontrol */
11931329 if (strnlen(mc->hdr.name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN) ==
11941330 SNDRV_CTL_ELEM_ID_NAME_MAXLEN)
1195
- goto err_str;
1331
+ goto err_sm;
1332
+
1333
+ sm = kzalloc(sizeof(*sm), GFP_KERNEL);
1334
+ if (sm == NULL)
1335
+ goto err_sm;
1336
+
1337
+ tplg->pos += (sizeof(struct snd_soc_tplg_mixer_control) +
1338
+ le32_to_cpu(mc->priv.size));
11961339
11971340 dev_dbg(tplg->dev, " adding DAPM widget mixer control %s at %d\n",
11981341 mc->hdr.name, i);
11991342
1343
+ kc[i].private_value = (long)sm;
12001344 kc[i].name = kstrdup(mc->hdr.name, GFP_KERNEL);
12011345 if (kc[i].name == NULL)
1202
- goto err_str;
1203
- kc[i].private_value = (long)sm;
1346
+ goto err_sm;
12041347 kc[i].iface = SNDRV_CTL_ELEM_IFACE_MIXER;
1205
- kc[i].access = mc->hdr.access;
1348
+ kc[i].access = le32_to_cpu(mc->hdr.access);
12061349
12071350 /* we only support FL/FR channel mapping atm */
12081351 sm->reg = tplc_chan_get_reg(tplg, mc->channel,
....@@ -1214,10 +1357,10 @@
12141357 sm->rshift = tplc_chan_get_shift(tplg, mc->channel,
12151358 SNDRV_CHMAP_FR);
12161359
1217
- sm->max = mc->max;
1218
- sm->min = mc->min;
1219
- sm->invert = mc->invert;
1220
- sm->platform_max = mc->platform_max;
1360
+ sm->max = le32_to_cpu(mc->max);
1361
+ sm->min = le32_to_cpu(mc->min);
1362
+ sm->invert = le32_to_cpu(mc->invert);
1363
+ sm->platform_max = le32_to_cpu(mc->platform_max);
12211364 sm->dobj.index = tplg->index;
12221365 INIT_LIST_HEAD(&sm->dobj.list);
12231366
....@@ -1225,8 +1368,15 @@
12251368 err = soc_tplg_kcontrol_bind_io(&mc->hdr, &kc[i], tplg);
12261369 if (err) {
12271370 soc_control_err(tplg, &mc->hdr, mc->hdr.name);
1228
- kfree(sm);
1229
- continue;
1371
+ goto err_sm;
1372
+ }
1373
+
1374
+ /* create any TLV data */
1375
+ err = soc_tplg_create_tlv(tplg, &kc[i], &mc->hdr);
1376
+ if (err < 0) {
1377
+ dev_err(tplg->dev, "ASoC: failed to create TLV %s\n",
1378
+ mc->hdr.name);
1379
+ goto err_sm;
12301380 }
12311381
12321382 /* pass control to driver for optional further init */
....@@ -1235,23 +1385,20 @@
12351385 if (err < 0) {
12361386 dev_err(tplg->dev, "ASoC: failed to init %s\n",
12371387 mc->hdr.name);
1238
- kfree(sm);
1239
- continue;
1388
+ goto err_sm;
12401389 }
1241
-
1242
- /* create any TLV data */
1243
- soc_tplg_create_tlv(tplg, &kc[i], &mc->hdr);
12441390 }
12451391 return kc;
12461392
1247
-err_str:
1248
- kfree(sm);
1249
-err:
1250
- for (--i; i >= 0; i--) {
1251
- kfree((void *)kc[i].private_value);
1393
+err_sm:
1394
+ for (; i >= 0; i--) {
1395
+ soc_tplg_free_tlv(tplg, &kc[i]);
1396
+ sm = (struct soc_mixer_control *)kc[i].private_value;
1397
+ kfree(sm);
12521398 kfree(kc[i].name);
12531399 }
12541400 kfree(kc);
1401
+
12551402 return NULL;
12561403 }
12571404
....@@ -1261,7 +1408,7 @@
12611408 struct snd_kcontrol_new *kc;
12621409 struct snd_soc_tplg_enum_control *ec;
12631410 struct soc_enum *se;
1264
- int i, j, err;
1411
+ int i, err;
12651412
12661413 kc = kcalloc(num_kcontrols, sizeof(*kc), GFP_KERNEL);
12671414 if (kc == NULL)
....@@ -1272,23 +1419,24 @@
12721419 /* validate kcontrol */
12731420 if (strnlen(ec->hdr.name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN) ==
12741421 SNDRV_CTL_ELEM_ID_NAME_MAXLEN)
1275
- goto err;
1422
+ goto err_se;
12761423
12771424 se = kzalloc(sizeof(*se), GFP_KERNEL);
12781425 if (se == NULL)
1279
- goto err;
1426
+ goto err_se;
1427
+
1428
+ tplg->pos += (sizeof(struct snd_soc_tplg_enum_control) +
1429
+ le32_to_cpu(ec->priv.size));
12801430
12811431 dev_dbg(tplg->dev, " adding DAPM widget enum control %s\n",
12821432 ec->hdr.name);
12831433
1284
- kc[i].name = kstrdup(ec->hdr.name, GFP_KERNEL);
1285
- if (kc[i].name == NULL) {
1286
- kfree(se);
1287
- goto err_se;
1288
- }
12891434 kc[i].private_value = (long)se;
1435
+ kc[i].name = kstrdup(ec->hdr.name, GFP_KERNEL);
1436
+ if (kc[i].name == NULL)
1437
+ goto err_se;
12901438 kc[i].iface = SNDRV_CTL_ELEM_IFACE_MIXER;
1291
- kc[i].access = ec->hdr.access;
1439
+ kc[i].access = le32_to_cpu(ec->hdr.access);
12921440
12931441 /* we only support FL/FR channel mapping atm */
12941442 se->reg = tplc_chan_get_reg(tplg, ec->channel, SNDRV_CHMAP_FL);
....@@ -1297,11 +1445,11 @@
12971445 se->shift_r = tplc_chan_get_shift(tplg, ec->channel,
12981446 SNDRV_CHMAP_FR);
12991447
1300
- se->items = ec->items;
1301
- se->mask = ec->mask;
1448
+ se->items = le32_to_cpu(ec->items);
1449
+ se->mask = le32_to_cpu(ec->mask);
13021450 se->dobj.index = tplg->index;
13031451
1304
- switch (ec->hdr.ops.info) {
1452
+ switch (le32_to_cpu(ec->hdr.ops.info)) {
13051453 case SND_SOC_TPLG_CTL_ENUM_VALUE:
13061454 case SND_SOC_TPLG_DAPM_CTL_ENUM_VALUE:
13071455 err = soc_tplg_denum_create_values(se, ec);
....@@ -1310,7 +1458,7 @@
13101458 ec->hdr.name);
13111459 goto err_se;
13121460 }
1313
- /* fall through to create texts */
1461
+ fallthrough;
13141462 case SND_SOC_TPLG_CTL_ENUM:
13151463 case SND_SOC_TPLG_DAPM_CTL_ENUM_DOUBLE:
13161464 case SND_SOC_TPLG_DAPM_CTL_ENUM_VIRT:
....@@ -1342,9 +1490,6 @@
13421490 ec->hdr.name);
13431491 goto err_se;
13441492 }
1345
-
1346
- tplg->pos += (sizeof(struct snd_soc_tplg_enum_control) +
1347
- ec->priv.size);
13481493 }
13491494
13501495 return kc;
....@@ -1353,71 +1498,66 @@
13531498 for (; i >= 0; i--) {
13541499 /* free values and texts */
13551500 se = (struct soc_enum *)kc[i].private_value;
1356
- if (!se)
1357
- continue;
13581501
1359
- kfree(se->dobj.control.dvalues);
1360
- for (j = 0; j < ec->items; j++)
1361
- kfree(se->dobj.control.dtexts[j]);
1502
+ if (se) {
1503
+ soc_tplg_denum_remove_values(se);
1504
+ soc_tplg_denum_remove_texts(se);
1505
+ }
13621506
13631507 kfree(se);
13641508 kfree(kc[i].name);
13651509 }
1366
-err:
13671510 kfree(kc);
13681511
13691512 return NULL;
13701513 }
13711514
13721515 static struct snd_kcontrol_new *soc_tplg_dapm_widget_dbytes_create(
1373
- struct soc_tplg *tplg, int count)
1516
+ struct soc_tplg *tplg, int num_kcontrols)
13741517 {
13751518 struct snd_soc_tplg_bytes_control *be;
1376
- struct soc_bytes_ext *sbe;
1519
+ struct soc_bytes_ext *sbe;
13771520 struct snd_kcontrol_new *kc;
13781521 int i, err;
13791522
1380
- kc = kcalloc(count, sizeof(*kc), GFP_KERNEL);
1523
+ kc = kcalloc(num_kcontrols, sizeof(*kc), GFP_KERNEL);
13811524 if (!kc)
13821525 return NULL;
13831526
1384
- for (i = 0; i < count; i++) {
1527
+ for (i = 0; i < num_kcontrols; i++) {
13851528 be = (struct snd_soc_tplg_bytes_control *)tplg->pos;
13861529
13871530 /* validate kcontrol */
13881531 if (strnlen(be->hdr.name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN) ==
13891532 SNDRV_CTL_ELEM_ID_NAME_MAXLEN)
1390
- goto err;
1533
+ goto err_sbe;
13911534
13921535 sbe = kzalloc(sizeof(*sbe), GFP_KERNEL);
13931536 if (sbe == NULL)
1394
- goto err;
1537
+ goto err_sbe;
13951538
13961539 tplg->pos += (sizeof(struct snd_soc_tplg_bytes_control) +
1397
- be->priv.size);
1540
+ le32_to_cpu(be->priv.size));
13981541
13991542 dev_dbg(tplg->dev,
14001543 "ASoC: adding bytes kcontrol %s with access 0x%x\n",
14011544 be->hdr.name, be->hdr.access);
14021545
1403
- kc[i].name = kstrdup(be->hdr.name, GFP_KERNEL);
1404
- if (kc[i].name == NULL) {
1405
- kfree(sbe);
1406
- goto err;
1407
- }
14081546 kc[i].private_value = (long)sbe;
1547
+ kc[i].name = kstrdup(be->hdr.name, GFP_KERNEL);
1548
+ if (kc[i].name == NULL)
1549
+ goto err_sbe;
14091550 kc[i].iface = SNDRV_CTL_ELEM_IFACE_MIXER;
1410
- kc[i].access = be->hdr.access;
1551
+ kc[i].access = le32_to_cpu(be->hdr.access);
14111552
1412
- sbe->max = be->max;
1553
+ sbe->max = le32_to_cpu(be->max);
14131554 INIT_LIST_HEAD(&sbe->dobj.list);
14141555
14151556 /* map standard io handlers and check for external handlers */
14161557 err = soc_tplg_kcontrol_bind_io(&be->hdr, &kc[i], tplg);
14171558 if (err) {
14181559 soc_control_err(tplg, &be->hdr, be->hdr.name);
1419
- kfree(sbe);
1420
- continue;
1560
+ goto err_sbe;
14211561 }
14221562
14231563 /* pass control to driver for optional further init */
....@@ -1426,20 +1566,20 @@
14261566 if (err < 0) {
14271567 dev_err(tplg->dev, "ASoC: failed to init %s\n",
14281568 be->hdr.name);
1429
- kfree(sbe);
1430
- continue;
1569
+ goto err_sbe;
14311570 }
14321571 }
14331572
14341573 return kc;
14351574
1436
-err:
1437
- for (--i; i >= 0; i--) {
1438
- kfree((void *)kc[i].private_value);
1575
+err_sbe:
1576
+ for (; i >= 0; i--) {
1577
+ sbe = (struct soc_bytes_ext *)kc[i].private_value;
1578
+ kfree(sbe);
14391579 kfree(kc[i].name);
14401580 }
1441
-
14421581 kfree(kc);
1582
+
14431583 return NULL;
14441584 }
14451585
....@@ -1466,8 +1606,8 @@
14661606 memset(&template, 0, sizeof(template));
14671607
14681608 /* map user to kernel widget ID */
1469
- template.id = get_widget_id(w->id);
1470
- if (template.id < 0)
1609
+ template.id = get_widget_id(le32_to_cpu(w->id));
1610
+ if ((int)template.id < 0)
14711611 return template.id;
14721612
14731613 /* strings are allocated here, but used and freed by the widget */
....@@ -1479,18 +1619,20 @@
14791619 ret = -ENOMEM;
14801620 goto err;
14811621 }
1482
- template.reg = w->reg;
1483
- template.shift = w->shift;
1484
- template.mask = w->mask;
1485
- template.subseq = w->subseq;
1622
+ template.reg = le32_to_cpu(w->reg);
1623
+ template.shift = le32_to_cpu(w->shift);
1624
+ template.mask = le32_to_cpu(w->mask);
1625
+ template.subseq = le32_to_cpu(w->subseq);
14861626 template.on_val = w->invert ? 0 : 1;
14871627 template.off_val = w->invert ? 1 : 0;
1488
- template.ignore_suspend = w->ignore_suspend;
1489
- template.event_flags = w->event_flags;
1628
+ template.ignore_suspend = le32_to_cpu(w->ignore_suspend);
1629
+ template.event_flags = le16_to_cpu(w->event_flags);
14901630 template.dobj.index = tplg->index;
14911631
14921632 tplg->pos +=
1493
- (sizeof(struct snd_soc_tplg_dapm_widget) + w->priv.size);
1633
+ (sizeof(struct snd_soc_tplg_dapm_widget) +
1634
+ le32_to_cpu(w->priv.size));
1635
+
14941636 if (w->num_kcontrols == 0) {
14951637 kcontrol_type = 0;
14961638 template.num_kcontrols = 0;
....@@ -1501,7 +1643,7 @@
15011643 dev_dbg(tplg->dev, "ASoC: template %s has %d controls of type %x\n",
15021644 w->name, w->num_kcontrols, control_hdr->type);
15031645
1504
- switch (control_hdr->ops.info) {
1646
+ switch (le32_to_cpu(control_hdr->ops.info)) {
15051647 case SND_SOC_TPLG_CTL_VOLSW:
15061648 case SND_SOC_TPLG_CTL_STROBE:
15071649 case SND_SOC_TPLG_CTL_VOLSW_SX:
....@@ -1509,7 +1651,7 @@
15091651 case SND_SOC_TPLG_CTL_RANGE:
15101652 case SND_SOC_TPLG_DAPM_CTL_VOLSW:
15111653 kcontrol_type = SND_SOC_TPLG_TYPE_MIXER; /* volume mixer */
1512
- template.num_kcontrols = w->num_kcontrols;
1654
+ template.num_kcontrols = le32_to_cpu(w->num_kcontrols);
15131655 template.kcontrol_news =
15141656 soc_tplg_dapm_widget_dmixer_create(tplg,
15151657 template.num_kcontrols);
....@@ -1524,7 +1666,7 @@
15241666 case SND_SOC_TPLG_DAPM_CTL_ENUM_VIRT:
15251667 case SND_SOC_TPLG_DAPM_CTL_ENUM_VALUE:
15261668 kcontrol_type = SND_SOC_TPLG_TYPE_ENUM; /* enumerated mixer */
1527
- template.num_kcontrols = w->num_kcontrols;
1669
+ template.num_kcontrols = le32_to_cpu(w->num_kcontrols);
15281670 template.kcontrol_news =
15291671 soc_tplg_dapm_widget_denum_create(tplg,
15301672 template.num_kcontrols);
....@@ -1535,7 +1677,7 @@
15351677 break;
15361678 case SND_SOC_TPLG_CTL_BYTES:
15371679 kcontrol_type = SND_SOC_TPLG_TYPE_BYTES; /* bytes control */
1538
- template.num_kcontrols = w->num_kcontrols;
1680
+ template.num_kcontrols = le32_to_cpu(w->num_kcontrols);
15391681 template.kcontrol_news =
15401682 soc_tplg_dapm_widget_dbytes_create(tplg,
15411683 template.num_kcontrols);
....@@ -1547,7 +1689,7 @@
15471689 default:
15481690 dev_err(tplg->dev, "ASoC: invalid widget control type %d:%d:%d\n",
15491691 control_hdr->ops.get, control_hdr->ops.put,
1550
- control_hdr->ops.info);
1692
+ le32_to_cpu(control_hdr->ops.info));
15511693 ret = -EINVAL;
15521694 goto hdr_err;
15531695 }
....@@ -1565,17 +1707,6 @@
15651707 widget = snd_soc_dapm_new_control_unlocked(dapm, &template);
15661708 if (IS_ERR(widget)) {
15671709 ret = PTR_ERR(widget);
1568
- /* Do not nag about probe deferrals */
1569
- if (ret != -EPROBE_DEFER)
1570
- dev_err(tplg->dev,
1571
- "ASoC: failed to create widget %s controls (%d)\n",
1572
- w->name, ret);
1573
- goto hdr_err;
1574
- }
1575
- if (widget == NULL) {
1576
- dev_err(tplg->dev, "ASoC: failed to create widget %s controls\n",
1577
- w->name);
1578
- ret = -ENOMEM;
15791710 goto hdr_err;
15801711 }
15811712
....@@ -1588,6 +1719,9 @@
15881719 ret = soc_tplg_widget_ready(tplg, widget, w);
15891720 if (ret < 0)
15901721 goto ready_err;
1722
+
1723
+ kfree(template.sname);
1724
+ kfree(template.name);
15911725
15921726 return 0;
15931727
....@@ -1605,16 +1739,15 @@
16051739 struct snd_soc_tplg_hdr *hdr)
16061740 {
16071741 struct snd_soc_tplg_dapm_widget *widget;
1608
- int ret, count = hdr->count, i;
1742
+ int ret, count, i;
16091743
1610
- if (tplg->pass != SOC_TPLG_PASS_WIDGET)
1611
- return 0;
1744
+ count = le32_to_cpu(hdr->count);
16121745
16131746 dev_dbg(tplg->dev, "ASoC: adding %d DAPM widgets\n", count);
16141747
16151748 for (i = 0; i < count; i++) {
16161749 widget = (struct snd_soc_tplg_dapm_widget *) tplg->pos;
1617
- if (widget->size != sizeof(*widget)) {
1750
+ if (le32_to_cpu(widget->size) != sizeof(*widget)) {
16181751 dev_err(tplg->dev, "ASoC: invalid widget size\n");
16191752 return -EINVAL;
16201753 }
....@@ -1652,17 +1785,22 @@
16521785 return 0;
16531786 }
16541787
1655
-static void set_stream_info(struct snd_soc_pcm_stream *stream,
1788
+static int set_stream_info(struct snd_soc_pcm_stream *stream,
16561789 struct snd_soc_tplg_stream_caps *caps)
16571790 {
16581791 stream->stream_name = kstrdup(caps->name, GFP_KERNEL);
1659
- stream->channels_min = caps->channels_min;
1660
- stream->channels_max = caps->channels_max;
1661
- stream->rates = caps->rates;
1662
- stream->rate_min = caps->rate_min;
1663
- stream->rate_max = caps->rate_max;
1664
- stream->formats = caps->formats;
1665
- stream->sig_bits = caps->sig_bits;
1792
+ if (!stream->stream_name)
1793
+ return -ENOMEM;
1794
+
1795
+ stream->channels_min = le32_to_cpu(caps->channels_min);
1796
+ stream->channels_max = le32_to_cpu(caps->channels_max);
1797
+ stream->rates = le32_to_cpu(caps->rates);
1798
+ stream->rate_min = le32_to_cpu(caps->rate_min);
1799
+ stream->rate_max = le32_to_cpu(caps->rate_max);
1800
+ stream->formats = le64_to_cpu(caps->formats);
1801
+ stream->sig_bits = le32_to_cpu(caps->sig_bits);
1802
+
1803
+ return 0;
16661804 }
16671805
16681806 static void set_dai_flags(struct snd_soc_dai_driver *dai_drv,
....@@ -1689,26 +1827,38 @@
16891827 struct snd_soc_dai_driver *dai_drv;
16901828 struct snd_soc_pcm_stream *stream;
16911829 struct snd_soc_tplg_stream_caps *caps;
1830
+ struct snd_soc_dai *dai;
1831
+ struct snd_soc_dapm_context *dapm =
1832
+ snd_soc_component_get_dapm(tplg->comp);
16921833 int ret;
16931834
16941835 dai_drv = kzalloc(sizeof(struct snd_soc_dai_driver), GFP_KERNEL);
16951836 if (dai_drv == NULL)
16961837 return -ENOMEM;
16971838
1698
- if (strlen(pcm->dai_name))
1839
+ if (strlen(pcm->dai_name)) {
16991840 dai_drv->name = kstrdup(pcm->dai_name, GFP_KERNEL);
1700
- dai_drv->id = pcm->dai_id;
1841
+ if (!dai_drv->name) {
1842
+ ret = -ENOMEM;
1843
+ goto err;
1844
+ }
1845
+ }
1846
+ dai_drv->id = le32_to_cpu(pcm->dai_id);
17011847
17021848 if (pcm->playback) {
17031849 stream = &dai_drv->playback;
17041850 caps = &pcm->caps[SND_SOC_TPLG_STREAM_PLAYBACK];
1705
- set_stream_info(stream, caps);
1851
+ ret = set_stream_info(stream, caps);
1852
+ if (ret < 0)
1853
+ goto err;
17061854 }
17071855
17081856 if (pcm->capture) {
17091857 stream = &dai_drv->capture;
17101858 caps = &pcm->caps[SND_SOC_TPLG_STREAM_CAPTURE];
1711
- set_stream_info(stream, caps);
1859
+ ret = set_stream_info(stream, caps);
1860
+ if (ret < 0)
1861
+ goto err;
17121862 }
17131863
17141864 if (pcm->compress)
....@@ -1718,8 +1868,7 @@
17181868 ret = soc_tplg_dai_load(tplg, dai_drv, pcm, NULL);
17191869 if (ret < 0) {
17201870 dev_err(tplg->comp->dev, "ASoC: DAI loading failed\n");
1721
- kfree(dai_drv);
1722
- return ret;
1871
+ goto err;
17231872 }
17241873
17251874 dai_drv->dobj.index = tplg->index;
....@@ -1728,7 +1877,27 @@
17281877 list_add(&dai_drv->dobj.list, &tplg->comp->dobj_list);
17291878
17301879 /* register the DAI to the component */
1731
- return snd_soc_register_dai(tplg->comp, dai_drv);
1880
+ dai = snd_soc_register_dai(tplg->comp, dai_drv, false);
1881
+ if (!dai)
1882
+ return -ENOMEM;
1883
+
1884
+ /* Create the DAI widgets here */
1885
+ ret = snd_soc_dapm_new_dai_widgets(dapm, dai);
1886
+ if (ret != 0) {
1887
+ dev_err(dai->dev, "Failed to create DAI widgets %d\n", ret);
1888
+ snd_soc_unregister_dai(dai);
1889
+ return ret;
1890
+ }
1891
+
1892
+ return 0;
1893
+
1894
+err:
1895
+ kfree(dai_drv->playback.stream_name);
1896
+ kfree(dai_drv->capture.stream_name);
1897
+ kfree(dai_drv->name);
1898
+ kfree(dai_drv);
1899
+
1900
+ return ret;
17321901 }
17331902
17341903 static void set_link_flags(struct snd_soc_dai_link *link,
....@@ -1759,46 +1928,82 @@
17591928 struct snd_soc_tplg_pcm *pcm)
17601929 {
17611930 struct snd_soc_dai_link *link;
1931
+ struct snd_soc_dai_link_component *dlc;
17621932 int ret;
17631933
1764
- link = kzalloc(sizeof(struct snd_soc_dai_link), GFP_KERNEL);
1934
+ /* link + cpu + codec + platform */
1935
+ link = kzalloc(sizeof(*link) + (3 * sizeof(*dlc)), GFP_KERNEL);
17651936 if (link == NULL)
17661937 return -ENOMEM;
1938
+
1939
+ dlc = (struct snd_soc_dai_link_component *)(link + 1);
1940
+
1941
+ link->cpus = &dlc[0];
1942
+ link->codecs = &dlc[1];
1943
+ link->platforms = &dlc[2];
1944
+
1945
+ link->num_cpus = 1;
1946
+ link->num_codecs = 1;
1947
+ link->num_platforms = 1;
1948
+
1949
+ link->dobj.index = tplg->index;
1950
+ link->dobj.ops = tplg->ops;
1951
+ link->dobj.type = SND_SOC_DOBJ_DAI_LINK;
17671952
17681953 if (strlen(pcm->pcm_name)) {
17691954 link->name = kstrdup(pcm->pcm_name, GFP_KERNEL);
17701955 link->stream_name = kstrdup(pcm->pcm_name, GFP_KERNEL);
1956
+ if (!link->name || !link->stream_name) {
1957
+ ret = -ENOMEM;
1958
+ goto err;
1959
+ }
17711960 }
1772
- link->id = pcm->pcm_id;
1961
+ link->id = le32_to_cpu(pcm->pcm_id);
17731962
1774
- if (strlen(pcm->dai_name))
1775
- link->cpu_dai_name = kstrdup(pcm->dai_name, GFP_KERNEL);
1963
+ if (strlen(pcm->dai_name)) {
1964
+ link->cpus->dai_name = kstrdup(pcm->dai_name, GFP_KERNEL);
1965
+ if (!link->cpus->dai_name) {
1966
+ ret = -ENOMEM;
1967
+ goto err;
1968
+ }
1969
+ }
17761970
1777
- link->codec_name = "snd-soc-dummy";
1778
- link->codec_dai_name = "snd-soc-dummy-dai";
1971
+ link->codecs->name = "snd-soc-dummy";
1972
+ link->codecs->dai_name = "snd-soc-dummy-dai";
1973
+
1974
+ link->platforms->name = "snd-soc-dummy";
17791975
17801976 /* enable DPCM */
17811977 link->dynamic = 1;
1782
- link->dpcm_playback = pcm->playback;
1783
- link->dpcm_capture = pcm->capture;
1978
+ link->dpcm_playback = le32_to_cpu(pcm->playback);
1979
+ link->dpcm_capture = le32_to_cpu(pcm->capture);
17841980 if (pcm->flag_mask)
1785
- set_link_flags(link, pcm->flag_mask, pcm->flags);
1981
+ set_link_flags(link,
1982
+ le32_to_cpu(pcm->flag_mask),
1983
+ le32_to_cpu(pcm->flags));
17861984
17871985 /* pass control to component driver for optional further init */
17881986 ret = soc_tplg_dai_link_load(tplg, link, NULL);
17891987 if (ret < 0) {
17901988 dev_err(tplg->comp->dev, "ASoC: FE link loading failed\n");
1791
- kfree(link);
1792
- return ret;
1989
+ goto err;
17931990 }
17941991
1795
- link->dobj.index = tplg->index;
1796
- link->dobj.ops = tplg->ops;
1797
- link->dobj.type = SND_SOC_DOBJ_DAI_LINK;
1992
+ ret = snd_soc_add_pcm_runtime(tplg->comp->card, link);
1993
+ if (ret < 0) {
1994
+ dev_err(tplg->comp->dev, "ASoC: adding FE link failed\n");
1995
+ goto err;
1996
+ }
1997
+
17981998 list_add(&link->dobj.list, &tplg->comp->dobj_list);
17991999
1800
- snd_soc_add_dai_link(tplg->comp->card, link);
18012000 return 0;
2001
+err:
2002
+ kfree(link->name);
2003
+ kfree(link->stream_name);
2004
+ kfree(link->cpus->dai_name);
2005
+ kfree(link);
2006
+ return ret;
18022007 }
18032008
18042009 /* create a FE DAI and DAI link from the PCM object */
....@@ -1818,7 +2023,7 @@
18182023 static void stream_caps_new_ver(struct snd_soc_tplg_stream_caps *dest,
18192024 struct snd_soc_tplg_stream_caps_v4 *src)
18202025 {
1821
- dest->size = sizeof(*dest);
2026
+ dest->size = cpu_to_le32(sizeof(*dest));
18222027 memcpy(dest->name, src->name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN);
18232028 dest->formats = src->formats;
18242029 dest->rates = src->rates;
....@@ -1852,7 +2057,7 @@
18522057
18532058 *pcm = NULL;
18542059
1855
- if (src->size != sizeof(*src_v4)) {
2060
+ if (le32_to_cpu(src->size) != sizeof(*src_v4)) {
18562061 dev_err(tplg->dev, "ASoC: invalid PCM size\n");
18572062 return -EINVAL;
18582063 }
....@@ -1863,7 +2068,7 @@
18632068 if (!dest)
18642069 return -ENOMEM;
18652070
1866
- dest->size = sizeof(*dest); /* size of latest abi version */
2071
+ dest->size = cpu_to_le32(sizeof(*dest)); /* size of latest abi version */
18672072 memcpy(dest->pcm_name, src_v4->pcm_name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN);
18682073 memcpy(dest->dai_name, src_v4->dai_name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN);
18692074 dest->pcm_id = src_v4->pcm_id;
....@@ -1872,7 +2077,7 @@
18722077 dest->capture = src_v4->capture;
18732078 dest->compress = src_v4->compress;
18742079 dest->num_streams = src_v4->num_streams;
1875
- for (i = 0; i < dest->num_streams; i++)
2080
+ for (i = 0; i < le32_to_cpu(dest->num_streams); i++)
18762081 memcpy(&dest->stream[i], &src_v4->stream[i],
18772082 sizeof(struct snd_soc_tplg_stream));
18782083
....@@ -1887,26 +2092,28 @@
18872092 struct snd_soc_tplg_hdr *hdr)
18882093 {
18892094 struct snd_soc_tplg_pcm *pcm, *_pcm;
1890
- int count = hdr->count;
2095
+ int count;
2096
+ int size;
18912097 int i;
18922098 bool abi_match;
18932099 int ret;
18942100
1895
- if (tplg->pass != SOC_TPLG_PASS_PCM_DAI)
1896
- return 0;
2101
+ count = le32_to_cpu(hdr->count);
18972102
18982103 /* check the element size and count */
18992104 pcm = (struct snd_soc_tplg_pcm *)tplg->pos;
1900
- if (pcm->size > sizeof(struct snd_soc_tplg_pcm)
1901
- || pcm->size < sizeof(struct snd_soc_tplg_pcm_v4)) {
2105
+ size = le32_to_cpu(pcm->size);
2106
+ if (size > sizeof(struct snd_soc_tplg_pcm)
2107
+ || size < sizeof(struct snd_soc_tplg_pcm_v4)) {
19022108 dev_err(tplg->dev, "ASoC: invalid size %d for PCM elems\n",
1903
- pcm->size);
2109
+ size);
19042110 return -EINVAL;
19052111 }
19062112
19072113 if (soc_tplg_check_elem_count(tplg,
1908
- pcm->size, count,
1909
- hdr->payload_size, "PCM DAI")) {
2114
+ size, count,
2115
+ le32_to_cpu(hdr->payload_size),
2116
+ "PCM DAI")) {
19102117 dev_err(tplg->dev, "ASoC: invalid count %d for PCM DAI elems\n",
19112118 count);
19122119 return -EINVAL;
....@@ -1914,11 +2121,12 @@
19142121
19152122 for (i = 0; i < count; i++) {
19162123 pcm = (struct snd_soc_tplg_pcm *)tplg->pos;
2124
+ size = le32_to_cpu(pcm->size);
19172125
19182126 /* check ABI version by size, create a new version of pcm
19192127 * if abi not match.
19202128 */
1921
- if (pcm->size == sizeof(*pcm)) {
2129
+ if (size == sizeof(*pcm)) {
19222130 abi_match = true;
19232131 _pcm = pcm;
19242132 } else {
....@@ -1939,7 +2147,7 @@
19392147 /* offset by version-specific struct size and
19402148 * real priv data size
19412149 */
1942
- tplg->pos += pcm->size + _pcm->priv.size;
2150
+ tplg->pos += size + le32_to_cpu(_pcm->priv.size);
19432151
19442152 if (!abi_match)
19452153 kfree(_pcm); /* free the duplicated one */
....@@ -1967,12 +2175,13 @@
19672175 unsigned char invert_bclk, invert_fsync;
19682176 int i;
19692177
1970
- for (i = 0; i < cfg->num_hw_configs; i++) {
2178
+ for (i = 0; i < le32_to_cpu(cfg->num_hw_configs); i++) {
19712179 hw_config = &cfg->hw_config[i];
19722180 if (hw_config->id != cfg->default_hw_config_id)
19732181 continue;
19742182
1975
- link->dai_fmt = hw_config->fmt & SND_SOC_DAIFMT_FORMAT_MASK;
2183
+ link->dai_fmt = le32_to_cpu(hw_config->fmt) &
2184
+ SND_SOC_DAIFMT_FORMAT_MASK;
19762185
19772186 /* clock gating */
19782187 switch (hw_config->clock_gated) {
....@@ -2036,7 +2245,8 @@
20362245
20372246 *link = NULL;
20382247
2039
- if (src->size != sizeof(struct snd_soc_tplg_link_config_v4)) {
2248
+ if (le32_to_cpu(src->size) !=
2249
+ sizeof(struct snd_soc_tplg_link_config_v4)) {
20402250 dev_err(tplg->dev, "ASoC: invalid physical link config size\n");
20412251 return -EINVAL;
20422252 }
....@@ -2048,15 +2258,56 @@
20482258 if (!dest)
20492259 return -ENOMEM;
20502260
2051
- dest->size = sizeof(*dest);
2261
+ dest->size = cpu_to_le32(sizeof(*dest));
20522262 dest->id = src_v4->id;
20532263 dest->num_streams = src_v4->num_streams;
2054
- for (i = 0; i < dest->num_streams; i++)
2264
+ for (i = 0; i < le32_to_cpu(dest->num_streams); i++)
20552265 memcpy(&dest->stream[i], &src_v4->stream[i],
20562266 sizeof(struct snd_soc_tplg_stream));
20572267
20582268 *link = dest;
20592269 return 0;
2270
+}
2271
+
2272
+/**
2273
+ * snd_soc_find_dai_link - Find a DAI link
2274
+ *
2275
+ * @card: soc card
2276
+ * @id: DAI link ID to match
2277
+ * @name: DAI link name to match, optional
2278
+ * @stream_name: DAI link stream name to match, optional
2279
+ *
2280
+ * This function will search all existing DAI links of the soc card to
2281
+ * find the link of the same ID. Since DAI links may not have their
2282
+ * unique ID, so name and stream name should also match if being
2283
+ * specified.
2284
+ *
2285
+ * Return: pointer of DAI link, or NULL if not found.
2286
+ */
2287
+static struct snd_soc_dai_link *snd_soc_find_dai_link(struct snd_soc_card *card,
2288
+ int id, const char *name,
2289
+ const char *stream_name)
2290
+{
2291
+ struct snd_soc_pcm_runtime *rtd;
2292
+ struct snd_soc_dai_link *link;
2293
+
2294
+ for_each_card_rtds(card, rtd) {
2295
+ link = rtd->dai_link;
2296
+
2297
+ if (link->id != id)
2298
+ continue;
2299
+
2300
+ if (name && (!link->name || strcmp(name, link->name)))
2301
+ continue;
2302
+
2303
+ if (stream_name && (!link->stream_name
2304
+ || strcmp(stream_name, link->stream_name)))
2305
+ continue;
2306
+
2307
+ return link;
2308
+ }
2309
+
2310
+ return NULL;
20602311 }
20612312
20622313 /* Find and configure an existing physical DAI link */
....@@ -2084,7 +2335,7 @@
20842335 else
20852336 stream_name = NULL;
20862337
2087
- link = snd_soc_find_dai_link(tplg->comp->card, cfg->id,
2338
+ link = snd_soc_find_dai_link(tplg->comp->card, le32_to_cpu(cfg->id),
20882339 name, stream_name);
20892340 if (!link) {
20902341 dev_err(tplg->dev, "ASoC: physical link %s (id %d) not exist\n",
....@@ -2098,7 +2349,9 @@
20982349
20992350 /* flags */
21002351 if (cfg->flag_mask)
2101
- set_link_flags(link, cfg->flag_mask, cfg->flags);
2352
+ set_link_flags(link,
2353
+ le32_to_cpu(cfg->flag_mask),
2354
+ le32_to_cpu(cfg->flags));
21022355
21032356 /* pass control to component driver for optional further init */
21042357 ret = soc_tplg_dai_link_load(tplg, link, cfg);
....@@ -2106,6 +2359,12 @@
21062359 dev_err(tplg->dev, "ASoC: physical link loading failed\n");
21072360 return ret;
21082361 }
2362
+
2363
+ /* for unloading it in snd_soc_tplg_component_remove */
2364
+ link->dobj.index = tplg->index;
2365
+ link->dobj.ops = tplg->ops;
2366
+ link->dobj.type = SND_SOC_DOBJ_BACKEND_LINK;
2367
+ list_add(&link->dobj.list, &tplg->comp->dobj_list);
21092368
21102369 return 0;
21112370 }
....@@ -2116,27 +2375,27 @@
21162375 struct snd_soc_tplg_hdr *hdr)
21172376 {
21182377 struct snd_soc_tplg_link_config *link, *_link;
2119
- int count = hdr->count;
2378
+ int count;
2379
+ int size;
21202380 int i, ret;
21212381 bool abi_match;
21222382
2123
- if (tplg->pass != SOC_TPLG_PASS_LINK) {
2124
- tplg->pos += hdr->size + hdr->payload_size;
2125
- return 0;
2126
- };
2383
+ count = le32_to_cpu(hdr->count);
21272384
21282385 /* check the element size and count */
21292386 link = (struct snd_soc_tplg_link_config *)tplg->pos;
2130
- if (link->size > sizeof(struct snd_soc_tplg_link_config)
2131
- || link->size < sizeof(struct snd_soc_tplg_link_config_v4)) {
2387
+ size = le32_to_cpu(link->size);
2388
+ if (size > sizeof(struct snd_soc_tplg_link_config)
2389
+ || size < sizeof(struct snd_soc_tplg_link_config_v4)) {
21322390 dev_err(tplg->dev, "ASoC: invalid size %d for physical link elems\n",
2133
- link->size);
2391
+ size);
21342392 return -EINVAL;
21352393 }
21362394
21372395 if (soc_tplg_check_elem_count(tplg,
2138
- link->size, count,
2139
- hdr->payload_size, "physical link config")) {
2396
+ size, count,
2397
+ le32_to_cpu(hdr->payload_size),
2398
+ "physical link config")) {
21402399 dev_err(tplg->dev, "ASoC: invalid count %d for physical link elems\n",
21412400 count);
21422401 return -EINVAL;
....@@ -2145,7 +2404,8 @@
21452404 /* config physical DAI links */
21462405 for (i = 0; i < count; i++) {
21472406 link = (struct snd_soc_tplg_link_config *)tplg->pos;
2148
- if (link->size == sizeof(*link)) {
2407
+ size = le32_to_cpu(link->size);
2408
+ if (size == sizeof(*link)) {
21492409 abi_match = true;
21502410 _link = link;
21512411 } else {
....@@ -2165,7 +2425,7 @@
21652425 /* offset by version-specific struct size and
21662426 * real priv data size
21672427 */
2168
- tplg->pos += link->size + _link->priv.size;
2428
+ tplg->pos += size + le32_to_cpu(_link->priv.size);
21692429
21702430 if (!abi_match)
21712431 kfree(_link); /* free the duplicated one */
....@@ -2185,12 +2445,14 @@
21852445 static int soc_tplg_dai_config(struct soc_tplg *tplg,
21862446 struct snd_soc_tplg_dai *d)
21872447 {
2188
- struct snd_soc_dai_link_component dai_component = {0};
2448
+ struct snd_soc_dai_link_component dai_component;
21892449 struct snd_soc_dai *dai;
21902450 struct snd_soc_dai_driver *dai_drv;
21912451 struct snd_soc_pcm_stream *stream;
21922452 struct snd_soc_tplg_stream_caps *caps;
21932453 int ret;
2454
+
2455
+ memset(&dai_component, 0, sizeof(dai_component));
21942456
21952457 dai_component.dai_name = d->dai_name;
21962458 dai = snd_soc_find_dai(&dai_component);
....@@ -2200,7 +2462,7 @@
22002462 return -EINVAL;
22012463 }
22022464
2203
- if (d->dai_id != dai->id) {
2465
+ if (le32_to_cpu(d->dai_id) != dai->id) {
22042466 dev_err(tplg->dev, "ASoC: physical DAI %s id mismatch\n",
22052467 d->dai_name);
22062468 return -EINVAL;
....@@ -2213,26 +2475,37 @@
22132475 if (d->playback) {
22142476 stream = &dai_drv->playback;
22152477 caps = &d->caps[SND_SOC_TPLG_STREAM_PLAYBACK];
2216
- set_stream_info(stream, caps);
2478
+ ret = set_stream_info(stream, caps);
2479
+ if (ret < 0)
2480
+ goto err;
22172481 }
22182482
22192483 if (d->capture) {
22202484 stream = &dai_drv->capture;
22212485 caps = &d->caps[SND_SOC_TPLG_STREAM_CAPTURE];
2222
- set_stream_info(stream, caps);
2486
+ ret = set_stream_info(stream, caps);
2487
+ if (ret < 0)
2488
+ goto err;
22232489 }
22242490
22252491 if (d->flag_mask)
2226
- set_dai_flags(dai_drv, d->flag_mask, d->flags);
2492
+ set_dai_flags(dai_drv,
2493
+ le32_to_cpu(d->flag_mask),
2494
+ le32_to_cpu(d->flags));
22272495
22282496 /* pass control to component driver for optional further init */
22292497 ret = soc_tplg_dai_load(tplg, dai_drv, NULL, dai);
22302498 if (ret < 0) {
22312499 dev_err(tplg->comp->dev, "ASoC: DAI loading failed\n");
2232
- return ret;
2500
+ goto err;
22332501 }
22342502
22352503 return 0;
2504
+
2505
+err:
2506
+ kfree(dai_drv->playback.stream_name);
2507
+ kfree(dai_drv->capture.stream_name);
2508
+ return ret;
22362509 }
22372510
22382511 /* load physical DAI elements */
....@@ -2240,22 +2513,26 @@
22402513 struct snd_soc_tplg_hdr *hdr)
22412514 {
22422515 struct snd_soc_tplg_dai *dai;
2243
- int count = hdr->count;
2244
- int i;
2516
+ int count;
2517
+ int i, ret;
22452518
2246
- if (tplg->pass != SOC_TPLG_PASS_BE_DAI)
2247
- return 0;
2519
+ count = le32_to_cpu(hdr->count);
22482520
22492521 /* config the existing BE DAIs */
22502522 for (i = 0; i < count; i++) {
22512523 dai = (struct snd_soc_tplg_dai *)tplg->pos;
2252
- if (dai->size != sizeof(*dai)) {
2524
+ if (le32_to_cpu(dai->size) != sizeof(*dai)) {
22532525 dev_err(tplg->dev, "ASoC: invalid physical DAI size\n");
22542526 return -EINVAL;
22552527 }
22562528
2257
- soc_tplg_dai_config(tplg, dai);
2258
- tplg->pos += (sizeof(*dai) + dai->priv.size);
2529
+ ret = soc_tplg_dai_config(tplg, dai);
2530
+ if (ret < 0) {
2531
+ dev_err(tplg->dev, "ASoC: failed to configure DAI\n");
2532
+ return ret;
2533
+ }
2534
+
2535
+ tplg->pos += (sizeof(*dai) + le32_to_cpu(dai->priv.size));
22592536 }
22602537
22612538 dev_dbg(tplg->dev, "ASoC: Configure %d BE DAIs\n", count);
....@@ -2277,25 +2554,28 @@
22772554 {
22782555 struct snd_soc_tplg_manifest *dest;
22792556 struct snd_soc_tplg_manifest_v4 *src_v4;
2557
+ int size;
22802558
22812559 *manifest = NULL;
22822560
2283
- if (src->size != sizeof(*src_v4)) {
2561
+ size = le32_to_cpu(src->size);
2562
+ if (size != sizeof(*src_v4)) {
22842563 dev_warn(tplg->dev, "ASoC: invalid manifest size %d\n",
2285
- src->size);
2286
- if (src->size)
2564
+ size);
2565
+ if (size)
22872566 return -EINVAL;
2288
- src->size = sizeof(*src_v4);
2567
+ src->size = cpu_to_le32(sizeof(*src_v4));
22892568 }
22902569
22912570 dev_warn(tplg->dev, "ASoC: old version of manifest\n");
22922571
22932572 src_v4 = (struct snd_soc_tplg_manifest_v4 *)src;
2294
- dest = kzalloc(sizeof(*dest) + src_v4->priv.size, GFP_KERNEL);
2573
+ dest = kzalloc(sizeof(*dest) + le32_to_cpu(src_v4->priv.size),
2574
+ GFP_KERNEL);
22952575 if (!dest)
22962576 return -ENOMEM;
22972577
2298
- dest->size = sizeof(*dest); /* size of latest abi version */
2578
+ dest->size = cpu_to_le32(sizeof(*dest)); /* size of latest abi version */
22992579 dest->control_elems = src_v4->control_elems;
23002580 dest->widget_elems = src_v4->widget_elems;
23012581 dest->graph_elems = src_v4->graph_elems;
....@@ -2304,7 +2584,7 @@
23042584 dest->priv.size = src_v4->priv.size;
23052585 if (dest->priv.size)
23062586 memcpy(dest->priv.data, src_v4->priv.data,
2307
- src_v4->priv.size);
2587
+ le32_to_cpu(src_v4->priv.size));
23082588
23092589 *manifest = dest;
23102590 return 0;
....@@ -2317,13 +2597,10 @@
23172597 bool abi_match;
23182598 int ret = 0;
23192599
2320
- if (tplg->pass != SOC_TPLG_PASS_MANIFEST)
2321
- return 0;
2322
-
23232600 manifest = (struct snd_soc_tplg_manifest *)tplg->pos;
23242601
23252602 /* check ABI version by size, create a new manifest if abi not match */
2326
- if (manifest->size == sizeof(*manifest)) {
2603
+ if (le32_to_cpu(manifest->size) == sizeof(*manifest)) {
23272604 abi_match = true;
23282605 _manifest = manifest;
23292606 } else {
....@@ -2334,7 +2611,7 @@
23342611 }
23352612
23362613 /* pass control to component driver for optional further init */
2337
- if (tplg->comp && tplg->ops && tplg->ops->manifest)
2614
+ if (tplg->ops && tplg->ops->manifest)
23382615 ret = tplg->ops->manifest(tplg->comp, tplg->index, _manifest);
23392616
23402617 if (!abi_match) /* free the duplicated one */
....@@ -2350,16 +2627,16 @@
23502627 if (soc_tplg_get_hdr_offset(tplg) >= tplg->fw->size)
23512628 return 0;
23522629
2353
- if (hdr->size != sizeof(*hdr)) {
2630
+ if (le32_to_cpu(hdr->size) != sizeof(*hdr)) {
23542631 dev_err(tplg->dev,
23552632 "ASoC: invalid header size for type %d at offset 0x%lx size 0x%zx.\n",
2356
- hdr->type, soc_tplg_get_hdr_offset(tplg),
2633
+ le32_to_cpu(hdr->type), soc_tplg_get_hdr_offset(tplg),
23572634 tplg->fw->size);
23582635 return -EINVAL;
23592636 }
23602637
23612638 /* big endian firmware objects not supported atm */
2362
- if (hdr->magic == cpu_to_be32(SND_SOC_TPLG_MAGIC)) {
2639
+ if (le32_to_cpu(hdr->magic) == SOC_TPLG_MAGIC_BIG_ENDIAN) {
23632640 dev_err(tplg->dev,
23642641 "ASoC: pass %d big endian not supported header got %x at offset 0x%lx size 0x%zx.\n",
23652642 tplg->pass, hdr->magic,
....@@ -2367,7 +2644,7 @@
23672644 return -EINVAL;
23682645 }
23692646
2370
- if (hdr->magic != SND_SOC_TPLG_MAGIC) {
2647
+ if (le32_to_cpu(hdr->magic) != SND_SOC_TPLG_MAGIC) {
23712648 dev_err(tplg->dev,
23722649 "ASoC: pass %d does not have a valid header got %x at offset 0x%lx size 0x%zx.\n",
23732650 tplg->pass, hdr->magic,
....@@ -2376,8 +2653,8 @@
23762653 }
23772654
23782655 /* Support ABI from version 4 */
2379
- if (hdr->abi > SND_SOC_TPLG_ABI_VERSION
2380
- || hdr->abi < SND_SOC_TPLG_ABI_VERSION_MIN) {
2656
+ if (le32_to_cpu(hdr->abi) > SND_SOC_TPLG_ABI_VERSION ||
2657
+ le32_to_cpu(hdr->abi) < SND_SOC_TPLG_ABI_VERSION_MIN) {
23812658 dev_err(tplg->dev,
23822659 "ASoC: pass %d invalid ABI version got 0x%x need 0x%x at offset 0x%lx size 0x%zx.\n",
23832660 tplg->pass, hdr->abi,
....@@ -2392,12 +2669,6 @@
23922669 return -EINVAL;
23932670 }
23942671
2395
- if (tplg->pass == hdr->type)
2396
- dev_dbg(tplg->dev,
2397
- "ASoC: Got 0x%x bytes of type %d version %d vendor %d at pass %d\n",
2398
- hdr->payload_size, hdr->type, hdr->version,
2399
- hdr->vendor_type, tplg->pass);
2400
-
24012672 return 1;
24022673 }
24032674
....@@ -2405,37 +2676,65 @@
24052676 static int soc_tplg_load_header(struct soc_tplg *tplg,
24062677 struct snd_soc_tplg_hdr *hdr)
24072678 {
2679
+ int (*elem_load)(struct soc_tplg *tplg,
2680
+ struct snd_soc_tplg_hdr *hdr);
2681
+ unsigned int hdr_pass;
2682
+
24082683 tplg->pos = tplg->hdr_pos + sizeof(struct snd_soc_tplg_hdr);
24092684
24102685 /* check for matching ID */
2411
- if (hdr->index != tplg->req_index &&
2686
+ if (le32_to_cpu(hdr->index) != tplg->req_index &&
24122687 tplg->req_index != SND_SOC_TPLG_INDEX_ALL)
24132688 return 0;
24142689
2415
- tplg->index = hdr->index;
2690
+ tplg->index = le32_to_cpu(hdr->index);
24162691
2417
- switch (hdr->type) {
2692
+ switch (le32_to_cpu(hdr->type)) {
24182693 case SND_SOC_TPLG_TYPE_MIXER:
24192694 case SND_SOC_TPLG_TYPE_ENUM:
24202695 case SND_SOC_TPLG_TYPE_BYTES:
2421
- return soc_tplg_kcontrol_elems_load(tplg, hdr);
2696
+ hdr_pass = SOC_TPLG_PASS_MIXER;
2697
+ elem_load = soc_tplg_kcontrol_elems_load;
2698
+ break;
24222699 case SND_SOC_TPLG_TYPE_DAPM_GRAPH:
2423
- return soc_tplg_dapm_graph_elems_load(tplg, hdr);
2700
+ hdr_pass = SOC_TPLG_PASS_GRAPH;
2701
+ elem_load = soc_tplg_dapm_graph_elems_load;
2702
+ break;
24242703 case SND_SOC_TPLG_TYPE_DAPM_WIDGET:
2425
- return soc_tplg_dapm_widget_elems_load(tplg, hdr);
2704
+ hdr_pass = SOC_TPLG_PASS_WIDGET;
2705
+ elem_load = soc_tplg_dapm_widget_elems_load;
2706
+ break;
24262707 case SND_SOC_TPLG_TYPE_PCM:
2427
- return soc_tplg_pcm_elems_load(tplg, hdr);
2708
+ hdr_pass = SOC_TPLG_PASS_PCM_DAI;
2709
+ elem_load = soc_tplg_pcm_elems_load;
2710
+ break;
24282711 case SND_SOC_TPLG_TYPE_DAI:
2429
- return soc_tplg_dai_elems_load(tplg, hdr);
2712
+ hdr_pass = SOC_TPLG_PASS_BE_DAI;
2713
+ elem_load = soc_tplg_dai_elems_load;
2714
+ break;
24302715 case SND_SOC_TPLG_TYPE_DAI_LINK:
24312716 case SND_SOC_TPLG_TYPE_BACKEND_LINK:
24322717 /* physical link configurations */
2433
- return soc_tplg_link_elems_load(tplg, hdr);
2718
+ hdr_pass = SOC_TPLG_PASS_LINK;
2719
+ elem_load = soc_tplg_link_elems_load;
2720
+ break;
24342721 case SND_SOC_TPLG_TYPE_MANIFEST:
2435
- return soc_tplg_manifest_load(tplg, hdr);
2722
+ hdr_pass = SOC_TPLG_PASS_MANIFEST;
2723
+ elem_load = soc_tplg_manifest_load;
2724
+ break;
24362725 default:
24372726 /* bespoke vendor data object */
2438
- return soc_tplg_vendor_load(tplg, hdr);
2727
+ hdr_pass = SOC_TPLG_PASS_VENDOR;
2728
+ elem_load = soc_tplg_vendor_load;
2729
+ break;
2730
+ }
2731
+
2732
+ if (tplg->pass == hdr_pass) {
2733
+ dev_dbg(tplg->dev,
2734
+ "ASoC: Got 0x%x bytes of type %d version %d vendor %d at pass %d\n",
2735
+ hdr->payload_size, hdr->type, hdr->version,
2736
+ hdr->vendor_type, tplg->pass);
2737
+ return elem_load(tplg, hdr);
24392738 }
24402739
24412740 return 0;
....@@ -2459,18 +2758,24 @@
24592758
24602759 /* make sure header is valid before loading */
24612760 ret = soc_valid_header(tplg, hdr);
2462
- if (ret < 0)
2761
+ if (ret < 0) {
2762
+ dev_err(tplg->dev,
2763
+ "ASoC: topology: invalid header: %d\n", ret);
24632764 return ret;
2464
- else if (ret == 0)
2765
+ } else if (ret == 0) {
24652766 break;
2767
+ }
24662768
24672769 /* load the header object */
24682770 ret = soc_tplg_load_header(tplg, hdr);
2469
- if (ret < 0)
2771
+ if (ret < 0) {
2772
+ dev_err(tplg->dev,
2773
+ "ASoC: topology: could not load header: %d\n", ret);
24702774 return ret;
2775
+ }
24712776
24722777 /* goto next header */
2473
- tplg->hdr_pos += hdr->payload_size +
2778
+ tplg->hdr_pos += le32_to_cpu(hdr->payload_size) +
24742779 sizeof(struct snd_soc_tplg_hdr);
24752780 hdr = (struct snd_soc_tplg_hdr *)tplg->hdr_pos;
24762781 }
....@@ -2505,6 +2810,10 @@
25052810 {
25062811 struct soc_tplg tplg;
25072812 int ret;
2813
+
2814
+ /* component needs to exist to keep and reference data while parsing */
2815
+ if (!comp)
2816
+ return -EINVAL;
25082817
25092818 /* setup parsing context */
25102819 memset(&tplg, 0, sizeof(tplg));
....@@ -2544,7 +2853,7 @@
25442853 {
25452854 struct snd_soc_dapm_widget *w, *next_w;
25462855
2547
- list_for_each_entry_safe(w, next_w, &dapm->card->widgets, list) {
2856
+ for_each_card_widgets_safe(dapm->card, w, next_w) {
25482857
25492858 /* make sure we are a widget with correct context */
25502859 if (w->dobj.type != SND_SOC_DOBJ_WIDGET || w->dapm != dapm)
....@@ -2592,6 +2901,9 @@
25922901 case SND_SOC_DOBJ_BYTES:
25932902 remove_bytes(comp, dobj, pass);
25942903 break;
2904
+ case SND_SOC_DOBJ_GRAPH:
2905
+ remove_route(comp, dobj, pass);
2906
+ break;
25952907 case SND_SOC_DOBJ_WIDGET:
25962908 remove_widget(comp, dobj, pass);
25972909 break;
....@@ -2601,6 +2913,13 @@
26012913 case SND_SOC_DOBJ_DAI_LINK:
26022914 remove_link(comp, dobj, pass);
26032915 break;
2916
+ case SND_SOC_DOBJ_BACKEND_LINK:
2917
+ /*
2918
+ * call link_unload ops if extra
2919
+ * deinitialization is needed.
2920
+ */
2921
+ remove_backend_link(comp, dobj, pass);
2922
+ break;
26042923 default:
26052924 dev_err(comp->dev, "ASoC: invalid component type %d for removal\n",
26062925 dobj->type);