Loading include/sound/soc-topology.h +1 −1 Original line number Diff line number Diff line Loading @@ -62,7 +62,7 @@ struct snd_soc_dobj { enum snd_soc_dobj_type type; unsigned int index; /* objects can belong in different groups */ struct list_head list; struct snd_soc_tplg_ops *ops; int (*unload)(struct snd_soc_component *comp, struct snd_soc_dobj *dobj); union { struct snd_soc_dobj_control control; struct snd_soc_dobj_widget widget; Loading sound/soc/soc-topology.c +73 −110 Original line number Diff line number Diff line Loading @@ -44,9 +44,8 @@ #define SOC_TPLG_PASS_WIDGET 3 #define SOC_TPLG_PASS_PCM_DAI 4 #define SOC_TPLG_PASS_GRAPH 5 #define SOC_TPLG_PASS_PINS 6 #define SOC_TPLG_PASS_BE_DAI 7 #define SOC_TPLG_PASS_LINK 8 #define SOC_TPLG_PASS_BE_DAI 6 #define SOC_TPLG_PASS_LINK 7 #define SOC_TPLG_PASS_START SOC_TPLG_PASS_MANIFEST #define SOC_TPLG_PASS_END SOC_TPLG_PASS_LINK Loading Loading @@ -77,9 +76,6 @@ struct soc_tplg { struct snd_soc_tplg_ops *ops; }; static int soc_tplg_process_headers(struct soc_tplg *tplg); static int soc_tplg_complete(struct soc_tplg *tplg); /* check we dont overflow the data for this control chunk */ static int soc_tplg_check_elem_count(struct soc_tplg *tplg, size_t elem_size, unsigned int count, size_t bytes, const char *elem_type) Loading Loading @@ -186,7 +182,7 @@ static const struct soc_tplg_map dapm_map[] = { {SND_SOC_TPLG_DAPM_DECODER, snd_soc_dapm_decoder}, }; static int tplc_chan_get_reg(struct soc_tplg *tplg, static int tplg_chan_get_reg(struct soc_tplg *tplg, struct snd_soc_tplg_channel *chan, int map) { int i; Loading @@ -199,7 +195,7 @@ static int tplc_chan_get_reg(struct soc_tplg *tplg, return -EINVAL; } static int tplc_chan_get_shift(struct soc_tplg *tplg, static int tplg_chan_get_shift(struct soc_tplg *tplg, struct snd_soc_tplg_channel *chan, int map) { int i; Loading Loading @@ -354,69 +350,37 @@ static int soc_tplg_add_kcontrol(struct soc_tplg *tplg, tplg->dev, k, comp->name_prefix, comp, kcontrol); } /* remove a mixer kcontrol */ static void remove_mixer(struct snd_soc_component *comp, struct snd_soc_dobj *dobj, int pass) { struct snd_card *card = comp->card->snd_card; if (pass != SOC_TPLG_PASS_CONTROL) return; if (dobj->ops && dobj->ops->control_unload) dobj->ops->control_unload(comp, dobj); snd_ctl_remove(card, dobj->control.kcontrol); list_del(&dobj->list); } /* remove an enum kcontrol */ static void remove_enum(struct snd_soc_component *comp, struct snd_soc_dobj *dobj, int pass) { struct snd_card *card = comp->card->snd_card; if (pass != SOC_TPLG_PASS_CONTROL) return; if (dobj->ops && dobj->ops->control_unload) dobj->ops->control_unload(comp, dobj); snd_ctl_remove(card, dobj->control.kcontrol); list_del(&dobj->list); } /* remove a byte kcontrol */ static void remove_bytes(struct snd_soc_component *comp, struct snd_soc_dobj *dobj, int pass) /* remove kcontrol */ static void soc_tplg_remove_kcontrol(struct snd_soc_component *comp, struct snd_soc_dobj *dobj, int pass) { struct snd_card *card = comp->card->snd_card; if (pass != SOC_TPLG_PASS_CONTROL) return; if (dobj->ops && dobj->ops->control_unload) dobj->ops->control_unload(comp, dobj); if (dobj->unload) dobj->unload(comp, dobj); snd_ctl_remove(card, dobj->control.kcontrol); list_del(&dobj->list); } /* remove a route */ static void remove_route(struct snd_soc_component *comp, static void soc_tplg_remove_route(struct snd_soc_component *comp, struct snd_soc_dobj *dobj, int pass) { if (pass != SOC_TPLG_PASS_GRAPH) return; if (dobj->ops && dobj->ops->dapm_route_unload) dobj->ops->dapm_route_unload(comp, dobj); if (dobj->unload) dobj->unload(comp, dobj); list_del(&dobj->list); } /* remove a widget and it's kcontrols - routes must be removed first */ static void remove_widget(struct snd_soc_component *comp, static void soc_tplg_remove_widget(struct snd_soc_component *comp, struct snd_soc_dobj *dobj, int pass) { struct snd_card *card = comp->card->snd_card; Loading @@ -427,8 +391,8 @@ static void remove_widget(struct snd_soc_component *comp, if (pass != SOC_TPLG_PASS_WIDGET) return; if (dobj->ops && dobj->ops->widget_unload) dobj->ops->widget_unload(comp, dobj); if (dobj->unload) dobj->unload(comp, dobj); if (!w->kcontrols) goto free_news; Loading @@ -444,7 +408,7 @@ static void remove_widget(struct snd_soc_component *comp, } /* remove DAI configurations */ static void remove_dai(struct snd_soc_component *comp, static void soc_tplg_remove_dai(struct snd_soc_component *comp, struct snd_soc_dobj *dobj, int pass) { struct snd_soc_dai_driver *dai_drv = Loading @@ -454,8 +418,8 @@ static void remove_dai(struct snd_soc_component *comp, if (pass != SOC_TPLG_PASS_PCM_DAI) return; if (dobj->ops && dobj->ops->dai_unload) dobj->ops->dai_unload(comp, dobj); if (dobj->unload) dobj->unload(comp, dobj); for_each_component_dais_safe(comp, dai, _dai) if (dai->driver == dai_drv) Loading @@ -465,7 +429,7 @@ static void remove_dai(struct snd_soc_component *comp, } /* remove link configurations */ static void remove_link(struct snd_soc_component *comp, static void soc_tplg_remove_link(struct snd_soc_component *comp, struct snd_soc_dobj *dobj, int pass) { struct snd_soc_dai_link *link = Loading @@ -474,8 +438,8 @@ static void remove_link(struct snd_soc_component *comp, if (pass != SOC_TPLG_PASS_PCM_DAI) return; if (dobj->ops && dobj->ops->link_unload) dobj->ops->link_unload(comp, dobj); if (dobj->unload) dobj->unload(comp, dobj); list_del(&dobj->list); snd_soc_remove_pcm_runtime(comp->card, Loading @@ -489,11 +453,11 @@ static void remove_backend_link(struct snd_soc_component *comp, if (pass != SOC_TPLG_PASS_LINK) return; if (dobj->ops && dobj->ops->link_unload) dobj->ops->link_unload(comp, dobj); if (dobj->unload) dobj->unload(comp, dobj); /* * We don't free the link here as what remove_link() do since BE * We don't free the link here as what soc_tplg_remove_link() do since BE * links are not allocated by topology. * We however need to reset the dobj type to its initial values */ Loading Loading @@ -714,7 +678,8 @@ static int soc_tplg_dbytes_create(struct soc_tplg *tplg, size_t size) sbe->max = le32_to_cpu(be->max); sbe->dobj.type = SND_SOC_DOBJ_BYTES; sbe->dobj.ops = tplg->ops; if (tplg->ops) sbe->dobj.unload = tplg->ops->control_unload; INIT_LIST_HEAD(&sbe->dobj.list); /* map io handlers */ Loading @@ -725,7 +690,7 @@ static int soc_tplg_dbytes_create(struct soc_tplg *tplg, size_t size) } /* pass control to driver for optional further init */ ret = soc_tplg_control_load(tplg, &kc, (struct snd_soc_tplg_ctl_hdr *)be); ret = soc_tplg_control_load(tplg, &kc, &be->hdr); if (ret < 0) { dev_err(tplg->dev, "ASoC: failed to init %s\n", be->hdr.name); goto err; Loading Loading @@ -780,18 +745,19 @@ static int soc_tplg_dmixer_create(struct soc_tplg *tplg, size_t size) kc.access = le32_to_cpu(mc->hdr.access); /* we only support FL/FR channel mapping atm */ sm->reg = tplc_chan_get_reg(tplg, mc->channel, SNDRV_CHMAP_FL); sm->rreg = tplc_chan_get_reg(tplg, mc->channel, SNDRV_CHMAP_FR); sm->shift = tplc_chan_get_shift(tplg, mc->channel, SNDRV_CHMAP_FL); sm->rshift = tplc_chan_get_shift(tplg, mc->channel, SNDRV_CHMAP_FR); sm->reg = tplg_chan_get_reg(tplg, mc->channel, SNDRV_CHMAP_FL); sm->rreg = tplg_chan_get_reg(tplg, mc->channel, SNDRV_CHMAP_FR); sm->shift = tplg_chan_get_shift(tplg, mc->channel, SNDRV_CHMAP_FL); sm->rshift = tplg_chan_get_shift(tplg, mc->channel, SNDRV_CHMAP_FR); sm->max = le32_to_cpu(mc->max); sm->min = le32_to_cpu(mc->min); sm->invert = le32_to_cpu(mc->invert); sm->platform_max = le32_to_cpu(mc->platform_max); sm->dobj.index = tplg->index; sm->dobj.ops = tplg->ops; sm->dobj.type = SND_SOC_DOBJ_MIXER; if (tplg->ops) sm->dobj.unload = tplg->ops->control_unload; INIT_LIST_HEAD(&sm->dobj.list); /* map io handlers */ Loading @@ -809,7 +775,7 @@ static int soc_tplg_dmixer_create(struct soc_tplg *tplg, size_t size) } /* pass control to driver for optional further init */ ret = soc_tplg_control_load(tplg, &kc, (struct snd_soc_tplg_ctl_hdr *)mc); ret = soc_tplg_control_load(tplg, &kc, &mc->hdr); if (ret < 0) { dev_err(tplg->dev, "ASoC: failed to init %s\n", mc->hdr.name); goto err; Loading Loading @@ -927,16 +893,17 @@ static int soc_tplg_denum_create(struct soc_tplg *tplg, size_t size) kc.iface = SNDRV_CTL_ELEM_IFACE_MIXER; kc.access = le32_to_cpu(ec->hdr.access); se->reg = tplc_chan_get_reg(tplg, ec->channel, SNDRV_CHMAP_FL); se->shift_l = tplc_chan_get_shift(tplg, ec->channel, se->reg = tplg_chan_get_reg(tplg, ec->channel, SNDRV_CHMAP_FL); se->shift_l = tplg_chan_get_shift(tplg, ec->channel, SNDRV_CHMAP_FL); se->shift_r = tplc_chan_get_shift(tplg, ec->channel, se->shift_r = tplg_chan_get_shift(tplg, ec->channel, SNDRV_CHMAP_FL); se->mask = le32_to_cpu(ec->mask); se->dobj.index = tplg->index; se->dobj.type = SND_SOC_DOBJ_ENUM; se->dobj.ops = tplg->ops; if (tplg->ops) se->dobj.unload = tplg->ops->control_unload; INIT_LIST_HEAD(&se->dobj.list); switch (le32_to_cpu(ec->hdr.ops.info)) { Loading Loading @@ -977,7 +944,7 @@ static int soc_tplg_denum_create(struct soc_tplg *tplg, size_t size) } /* pass control to driver for optional further init */ ret = soc_tplg_control_load(tplg, &kc, (struct snd_soc_tplg_ctl_hdr *)ec); ret = soc_tplg_control_load(tplg, &kc, &ec->hdr); if (ret < 0) { dev_err(tplg->dev, "ASoC: failed to init %s\n", ec->hdr.name); goto err; Loading Loading @@ -1113,7 +1080,8 @@ static int soc_tplg_dapm_graph_elems_load(struct soc_tplg *tplg, /* add route dobj to dobj_list */ route->dobj.type = SND_SOC_DOBJ_GRAPH; route->dobj.ops = tplg->ops; if (tplg->ops) route->dobj.unload = tplg->ops->control_unload; route->dobj.index = tplg->index; list_add(&route->dobj.list, &tplg->comp->dobj_list); Loading Loading @@ -1161,13 +1129,13 @@ static int soc_tplg_dapm_widget_dmixer_create(struct soc_tplg *tplg, struct snd_ kc->access = le32_to_cpu(mc->hdr.access); /* we only support FL/FR channel mapping atm */ sm->reg = tplc_chan_get_reg(tplg, mc->channel, sm->reg = tplg_chan_get_reg(tplg, mc->channel, SNDRV_CHMAP_FL); sm->rreg = tplc_chan_get_reg(tplg, mc->channel, sm->rreg = tplg_chan_get_reg(tplg, mc->channel, SNDRV_CHMAP_FR); sm->shift = tplc_chan_get_shift(tplg, mc->channel, sm->shift = tplg_chan_get_shift(tplg, mc->channel, SNDRV_CHMAP_FL); sm->rshift = tplc_chan_get_shift(tplg, mc->channel, sm->rshift = tplg_chan_get_shift(tplg, mc->channel, SNDRV_CHMAP_FR); sm->max = le32_to_cpu(mc->max); Loading @@ -1193,7 +1161,7 @@ static int soc_tplg_dapm_widget_dmixer_create(struct soc_tplg *tplg, struct snd_ } /* pass control to driver for optional further init */ err = soc_tplg_control_load(tplg, kc, (struct snd_soc_tplg_ctl_hdr *)mc); err = soc_tplg_control_load(tplg, kc, &mc->hdr); if (err < 0) { dev_err(tplg->dev, "ASoC: failed to init %s\n", mc->hdr.name); Loading Loading @@ -1233,10 +1201,10 @@ static int soc_tplg_dapm_widget_denum_create(struct soc_tplg *tplg, struct snd_k kc->access = le32_to_cpu(ec->hdr.access); /* we only support FL/FR channel mapping atm */ se->reg = tplc_chan_get_reg(tplg, ec->channel, SNDRV_CHMAP_FL); se->shift_l = tplc_chan_get_shift(tplg, ec->channel, se->reg = tplg_chan_get_reg(tplg, ec->channel, SNDRV_CHMAP_FL); se->shift_l = tplg_chan_get_shift(tplg, ec->channel, SNDRV_CHMAP_FL); se->shift_r = tplc_chan_get_shift(tplg, ec->channel, se->shift_r = tplg_chan_get_shift(tplg, ec->channel, SNDRV_CHMAP_FR); se->items = le32_to_cpu(ec->items); Loading Loading @@ -1277,7 +1245,7 @@ static int soc_tplg_dapm_widget_denum_create(struct soc_tplg *tplg, struct snd_k } /* pass control to driver for optional further init */ err = soc_tplg_control_load(tplg, kc, (struct snd_soc_tplg_ctl_hdr *)ec); err = soc_tplg_control_load(tplg, kc, &ec->hdr); if (err < 0) { dev_err(tplg->dev, "ASoC: failed to init %s\n", ec->hdr.name); Loading Loading @@ -1329,7 +1297,7 @@ static int soc_tplg_dapm_widget_dbytes_create(struct soc_tplg *tplg, struct snd_ } /* pass control to driver for optional further init */ err = soc_tplg_control_load(tplg, kc, (struct snd_soc_tplg_ctl_hdr *)be); err = soc_tplg_control_load(tplg, kc, &be->hdr); if (err < 0) { dev_err(tplg->dev, "ASoC: failed to init %s\n", be->hdr.name); Loading Loading @@ -1479,7 +1447,8 @@ static int soc_tplg_dapm_widget_create(struct soc_tplg *tplg, widget->dobj.type = SND_SOC_DOBJ_WIDGET; widget->dobj.widget.kcontrol_type = kcontrol_type; widget->dobj.ops = tplg->ops; if (tplg->ops) widget->dobj.unload = tplg->ops->widget_unload; widget->dobj.index = tplg->index; list_add(&widget->dobj.list, &tplg->comp->dobj_list); Loading @@ -1493,7 +1462,7 @@ static int soc_tplg_dapm_widget_create(struct soc_tplg *tplg, return 0; ready_err: remove_widget(widget->dapm->component, &widget->dobj, SOC_TPLG_PASS_WIDGET); soc_tplg_remove_widget(widget->dapm->component, &widget->dobj, SOC_TPLG_PASS_WIDGET); snd_soc_dapm_free_widget(widget); hdr_err: kfree(template.sname); Loading Loading @@ -1567,7 +1536,7 @@ static int soc_tplg_dapm_complete(struct soc_tplg *tplg) dev_err(tplg->dev, "ASoC: failed to create new widgets %d\n", ret); return 0; return ret; } static int set_stream_info(struct soc_tplg *tplg, struct snd_soc_pcm_stream *stream, Loading Loading @@ -1657,8 +1626,9 @@ static int soc_tplg_dai_create(struct soc_tplg *tplg, } dai_drv->dobj.index = tplg->index; dai_drv->dobj.ops = tplg->ops; dai_drv->dobj.type = SND_SOC_DOBJ_PCM; if (tplg->ops) dai_drv->dobj.unload = tplg->ops->dai_unload; list_add(&dai_drv->dobj.list, &tplg->comp->dobj_list); /* register the DAI to the component */ Loading Loading @@ -1727,8 +1697,9 @@ static int soc_tplg_fe_link_create(struct soc_tplg *tplg, link->num_platforms = 1; link->dobj.index = tplg->index; link->dobj.ops = tplg->ops; link->dobj.type = SND_SOC_DOBJ_DAI_LINK; if (tplg->ops) link->dobj.unload = tplg->ops->link_unload; if (strlen(pcm->pcm_name)) { link->name = devm_kstrdup(tplg->dev, pcm->pcm_name, GFP_KERNEL); Loading Loading @@ -2135,8 +2106,9 @@ static int soc_tplg_link_config(struct soc_tplg *tplg, /* for unloading it in snd_soc_tplg_component_remove */ link->dobj.index = tplg->index; link->dobj.ops = tplg->ops; link->dobj.type = SND_SOC_DOBJ_BACKEND_LINK; if (tplg->ops) link->dobj.unload = tplg->ops->link_unload; list_add(&link->dobj.list, &tplg->comp->dobj_list); return 0; Loading Loading @@ -2390,12 +2362,9 @@ static int soc_tplg_manifest_load(struct soc_tplg *tplg, } /* validate header magic, size and type */ static int soc_valid_header(struct soc_tplg *tplg, static int soc_tplg_valid_header(struct soc_tplg *tplg, struct snd_soc_tplg_hdr *hdr) { if (soc_tplg_get_hdr_offset(tplg) >= tplg->fw->size) return 0; if (le32_to_cpu(hdr->size) != sizeof(*hdr)) { dev_err(tplg->dev, "ASoC: invalid header size for type %d at offset 0x%lx size 0x%zx.\n", Loading @@ -2404,7 +2373,7 @@ static int soc_valid_header(struct soc_tplg *tplg, return -EINVAL; } if (soc_tplg_get_hdr_offset(tplg) + hdr->payload_size >= tplg->fw->size) { if (soc_tplg_get_hdr_offset(tplg) + le32_to_cpu(hdr->payload_size) >= tplg->fw->size) { dev_err(tplg->dev, "ASoC: invalid header of type %d at offset %ld payload_size %d\n", le32_to_cpu(hdr->type), soc_tplg_get_hdr_offset(tplg), Loading Loading @@ -2446,7 +2415,7 @@ static int soc_valid_header(struct soc_tplg *tplg, return -EINVAL; } return 1; return 0; } /* check header type and call appropriate handler */ Loading Loading @@ -2527,13 +2496,11 @@ static int soc_tplg_process_headers(struct soc_tplg *tplg) while (!soc_tplg_is_eof(tplg)) { /* make sure header is valid before loading */ ret = soc_valid_header(tplg, hdr); ret = soc_tplg_valid_header(tplg, hdr); if (ret < 0) { dev_err(tplg->dev, "ASoC: topology: invalid header: %d\n", ret); return ret; } else if (ret == 0) { break; } /* load the header object */ Loading Loading @@ -2627,26 +2594,22 @@ int snd_soc_tplg_component_remove(struct snd_soc_component *comp) list) { switch (dobj->type) { case SND_SOC_DOBJ_MIXER: remove_mixer(comp, dobj, pass); break; case SND_SOC_DOBJ_ENUM: remove_enum(comp, dobj, pass); break; case SND_SOC_DOBJ_BYTES: remove_bytes(comp, dobj, pass); case SND_SOC_DOBJ_ENUM: case SND_SOC_DOBJ_MIXER: soc_tplg_remove_kcontrol(comp, dobj, pass); break; case SND_SOC_DOBJ_GRAPH: remove_route(comp, dobj, pass); soc_tplg_remove_route(comp, dobj, pass); break; case SND_SOC_DOBJ_WIDGET: remove_widget(comp, dobj, pass); soc_tplg_remove_widget(comp, dobj, pass); break; case SND_SOC_DOBJ_PCM: remove_dai(comp, dobj, pass); soc_tplg_remove_dai(comp, dobj, pass); break; case SND_SOC_DOBJ_DAI_LINK: remove_link(comp, dobj, pass); soc_tplg_remove_link(comp, dobj, pass); break; case SND_SOC_DOBJ_BACKEND_LINK: /* Loading Loading
include/sound/soc-topology.h +1 −1 Original line number Diff line number Diff line Loading @@ -62,7 +62,7 @@ struct snd_soc_dobj { enum snd_soc_dobj_type type; unsigned int index; /* objects can belong in different groups */ struct list_head list; struct snd_soc_tplg_ops *ops; int (*unload)(struct snd_soc_component *comp, struct snd_soc_dobj *dobj); union { struct snd_soc_dobj_control control; struct snd_soc_dobj_widget widget; Loading
sound/soc/soc-topology.c +73 −110 Original line number Diff line number Diff line Loading @@ -44,9 +44,8 @@ #define SOC_TPLG_PASS_WIDGET 3 #define SOC_TPLG_PASS_PCM_DAI 4 #define SOC_TPLG_PASS_GRAPH 5 #define SOC_TPLG_PASS_PINS 6 #define SOC_TPLG_PASS_BE_DAI 7 #define SOC_TPLG_PASS_LINK 8 #define SOC_TPLG_PASS_BE_DAI 6 #define SOC_TPLG_PASS_LINK 7 #define SOC_TPLG_PASS_START SOC_TPLG_PASS_MANIFEST #define SOC_TPLG_PASS_END SOC_TPLG_PASS_LINK Loading Loading @@ -77,9 +76,6 @@ struct soc_tplg { struct snd_soc_tplg_ops *ops; }; static int soc_tplg_process_headers(struct soc_tplg *tplg); static int soc_tplg_complete(struct soc_tplg *tplg); /* check we dont overflow the data for this control chunk */ static int soc_tplg_check_elem_count(struct soc_tplg *tplg, size_t elem_size, unsigned int count, size_t bytes, const char *elem_type) Loading Loading @@ -186,7 +182,7 @@ static const struct soc_tplg_map dapm_map[] = { {SND_SOC_TPLG_DAPM_DECODER, snd_soc_dapm_decoder}, }; static int tplc_chan_get_reg(struct soc_tplg *tplg, static int tplg_chan_get_reg(struct soc_tplg *tplg, struct snd_soc_tplg_channel *chan, int map) { int i; Loading @@ -199,7 +195,7 @@ static int tplc_chan_get_reg(struct soc_tplg *tplg, return -EINVAL; } static int tplc_chan_get_shift(struct soc_tplg *tplg, static int tplg_chan_get_shift(struct soc_tplg *tplg, struct snd_soc_tplg_channel *chan, int map) { int i; Loading Loading @@ -354,69 +350,37 @@ static int soc_tplg_add_kcontrol(struct soc_tplg *tplg, tplg->dev, k, comp->name_prefix, comp, kcontrol); } /* remove a mixer kcontrol */ static void remove_mixer(struct snd_soc_component *comp, struct snd_soc_dobj *dobj, int pass) { struct snd_card *card = comp->card->snd_card; if (pass != SOC_TPLG_PASS_CONTROL) return; if (dobj->ops && dobj->ops->control_unload) dobj->ops->control_unload(comp, dobj); snd_ctl_remove(card, dobj->control.kcontrol); list_del(&dobj->list); } /* remove an enum kcontrol */ static void remove_enum(struct snd_soc_component *comp, struct snd_soc_dobj *dobj, int pass) { struct snd_card *card = comp->card->snd_card; if (pass != SOC_TPLG_PASS_CONTROL) return; if (dobj->ops && dobj->ops->control_unload) dobj->ops->control_unload(comp, dobj); snd_ctl_remove(card, dobj->control.kcontrol); list_del(&dobj->list); } /* remove a byte kcontrol */ static void remove_bytes(struct snd_soc_component *comp, struct snd_soc_dobj *dobj, int pass) /* remove kcontrol */ static void soc_tplg_remove_kcontrol(struct snd_soc_component *comp, struct snd_soc_dobj *dobj, int pass) { struct snd_card *card = comp->card->snd_card; if (pass != SOC_TPLG_PASS_CONTROL) return; if (dobj->ops && dobj->ops->control_unload) dobj->ops->control_unload(comp, dobj); if (dobj->unload) dobj->unload(comp, dobj); snd_ctl_remove(card, dobj->control.kcontrol); list_del(&dobj->list); } /* remove a route */ static void remove_route(struct snd_soc_component *comp, static void soc_tplg_remove_route(struct snd_soc_component *comp, struct snd_soc_dobj *dobj, int pass) { if (pass != SOC_TPLG_PASS_GRAPH) return; if (dobj->ops && dobj->ops->dapm_route_unload) dobj->ops->dapm_route_unload(comp, dobj); if (dobj->unload) dobj->unload(comp, dobj); list_del(&dobj->list); } /* remove a widget and it's kcontrols - routes must be removed first */ static void remove_widget(struct snd_soc_component *comp, static void soc_tplg_remove_widget(struct snd_soc_component *comp, struct snd_soc_dobj *dobj, int pass) { struct snd_card *card = comp->card->snd_card; Loading @@ -427,8 +391,8 @@ static void remove_widget(struct snd_soc_component *comp, if (pass != SOC_TPLG_PASS_WIDGET) return; if (dobj->ops && dobj->ops->widget_unload) dobj->ops->widget_unload(comp, dobj); if (dobj->unload) dobj->unload(comp, dobj); if (!w->kcontrols) goto free_news; Loading @@ -444,7 +408,7 @@ static void remove_widget(struct snd_soc_component *comp, } /* remove DAI configurations */ static void remove_dai(struct snd_soc_component *comp, static void soc_tplg_remove_dai(struct snd_soc_component *comp, struct snd_soc_dobj *dobj, int pass) { struct snd_soc_dai_driver *dai_drv = Loading @@ -454,8 +418,8 @@ static void remove_dai(struct snd_soc_component *comp, if (pass != SOC_TPLG_PASS_PCM_DAI) return; if (dobj->ops && dobj->ops->dai_unload) dobj->ops->dai_unload(comp, dobj); if (dobj->unload) dobj->unload(comp, dobj); for_each_component_dais_safe(comp, dai, _dai) if (dai->driver == dai_drv) Loading @@ -465,7 +429,7 @@ static void remove_dai(struct snd_soc_component *comp, } /* remove link configurations */ static void remove_link(struct snd_soc_component *comp, static void soc_tplg_remove_link(struct snd_soc_component *comp, struct snd_soc_dobj *dobj, int pass) { struct snd_soc_dai_link *link = Loading @@ -474,8 +438,8 @@ static void remove_link(struct snd_soc_component *comp, if (pass != SOC_TPLG_PASS_PCM_DAI) return; if (dobj->ops && dobj->ops->link_unload) dobj->ops->link_unload(comp, dobj); if (dobj->unload) dobj->unload(comp, dobj); list_del(&dobj->list); snd_soc_remove_pcm_runtime(comp->card, Loading @@ -489,11 +453,11 @@ static void remove_backend_link(struct snd_soc_component *comp, if (pass != SOC_TPLG_PASS_LINK) return; if (dobj->ops && dobj->ops->link_unload) dobj->ops->link_unload(comp, dobj); if (dobj->unload) dobj->unload(comp, dobj); /* * We don't free the link here as what remove_link() do since BE * We don't free the link here as what soc_tplg_remove_link() do since BE * links are not allocated by topology. * We however need to reset the dobj type to its initial values */ Loading Loading @@ -714,7 +678,8 @@ static int soc_tplg_dbytes_create(struct soc_tplg *tplg, size_t size) sbe->max = le32_to_cpu(be->max); sbe->dobj.type = SND_SOC_DOBJ_BYTES; sbe->dobj.ops = tplg->ops; if (tplg->ops) sbe->dobj.unload = tplg->ops->control_unload; INIT_LIST_HEAD(&sbe->dobj.list); /* map io handlers */ Loading @@ -725,7 +690,7 @@ static int soc_tplg_dbytes_create(struct soc_tplg *tplg, size_t size) } /* pass control to driver for optional further init */ ret = soc_tplg_control_load(tplg, &kc, (struct snd_soc_tplg_ctl_hdr *)be); ret = soc_tplg_control_load(tplg, &kc, &be->hdr); if (ret < 0) { dev_err(tplg->dev, "ASoC: failed to init %s\n", be->hdr.name); goto err; Loading Loading @@ -780,18 +745,19 @@ static int soc_tplg_dmixer_create(struct soc_tplg *tplg, size_t size) kc.access = le32_to_cpu(mc->hdr.access); /* we only support FL/FR channel mapping atm */ sm->reg = tplc_chan_get_reg(tplg, mc->channel, SNDRV_CHMAP_FL); sm->rreg = tplc_chan_get_reg(tplg, mc->channel, SNDRV_CHMAP_FR); sm->shift = tplc_chan_get_shift(tplg, mc->channel, SNDRV_CHMAP_FL); sm->rshift = tplc_chan_get_shift(tplg, mc->channel, SNDRV_CHMAP_FR); sm->reg = tplg_chan_get_reg(tplg, mc->channel, SNDRV_CHMAP_FL); sm->rreg = tplg_chan_get_reg(tplg, mc->channel, SNDRV_CHMAP_FR); sm->shift = tplg_chan_get_shift(tplg, mc->channel, SNDRV_CHMAP_FL); sm->rshift = tplg_chan_get_shift(tplg, mc->channel, SNDRV_CHMAP_FR); sm->max = le32_to_cpu(mc->max); sm->min = le32_to_cpu(mc->min); sm->invert = le32_to_cpu(mc->invert); sm->platform_max = le32_to_cpu(mc->platform_max); sm->dobj.index = tplg->index; sm->dobj.ops = tplg->ops; sm->dobj.type = SND_SOC_DOBJ_MIXER; if (tplg->ops) sm->dobj.unload = tplg->ops->control_unload; INIT_LIST_HEAD(&sm->dobj.list); /* map io handlers */ Loading @@ -809,7 +775,7 @@ static int soc_tplg_dmixer_create(struct soc_tplg *tplg, size_t size) } /* pass control to driver for optional further init */ ret = soc_tplg_control_load(tplg, &kc, (struct snd_soc_tplg_ctl_hdr *)mc); ret = soc_tplg_control_load(tplg, &kc, &mc->hdr); if (ret < 0) { dev_err(tplg->dev, "ASoC: failed to init %s\n", mc->hdr.name); goto err; Loading Loading @@ -927,16 +893,17 @@ static int soc_tplg_denum_create(struct soc_tplg *tplg, size_t size) kc.iface = SNDRV_CTL_ELEM_IFACE_MIXER; kc.access = le32_to_cpu(ec->hdr.access); se->reg = tplc_chan_get_reg(tplg, ec->channel, SNDRV_CHMAP_FL); se->shift_l = tplc_chan_get_shift(tplg, ec->channel, se->reg = tplg_chan_get_reg(tplg, ec->channel, SNDRV_CHMAP_FL); se->shift_l = tplg_chan_get_shift(tplg, ec->channel, SNDRV_CHMAP_FL); se->shift_r = tplc_chan_get_shift(tplg, ec->channel, se->shift_r = tplg_chan_get_shift(tplg, ec->channel, SNDRV_CHMAP_FL); se->mask = le32_to_cpu(ec->mask); se->dobj.index = tplg->index; se->dobj.type = SND_SOC_DOBJ_ENUM; se->dobj.ops = tplg->ops; if (tplg->ops) se->dobj.unload = tplg->ops->control_unload; INIT_LIST_HEAD(&se->dobj.list); switch (le32_to_cpu(ec->hdr.ops.info)) { Loading Loading @@ -977,7 +944,7 @@ static int soc_tplg_denum_create(struct soc_tplg *tplg, size_t size) } /* pass control to driver for optional further init */ ret = soc_tplg_control_load(tplg, &kc, (struct snd_soc_tplg_ctl_hdr *)ec); ret = soc_tplg_control_load(tplg, &kc, &ec->hdr); if (ret < 0) { dev_err(tplg->dev, "ASoC: failed to init %s\n", ec->hdr.name); goto err; Loading Loading @@ -1113,7 +1080,8 @@ static int soc_tplg_dapm_graph_elems_load(struct soc_tplg *tplg, /* add route dobj to dobj_list */ route->dobj.type = SND_SOC_DOBJ_GRAPH; route->dobj.ops = tplg->ops; if (tplg->ops) route->dobj.unload = tplg->ops->control_unload; route->dobj.index = tplg->index; list_add(&route->dobj.list, &tplg->comp->dobj_list); Loading Loading @@ -1161,13 +1129,13 @@ static int soc_tplg_dapm_widget_dmixer_create(struct soc_tplg *tplg, struct snd_ kc->access = le32_to_cpu(mc->hdr.access); /* we only support FL/FR channel mapping atm */ sm->reg = tplc_chan_get_reg(tplg, mc->channel, sm->reg = tplg_chan_get_reg(tplg, mc->channel, SNDRV_CHMAP_FL); sm->rreg = tplc_chan_get_reg(tplg, mc->channel, sm->rreg = tplg_chan_get_reg(tplg, mc->channel, SNDRV_CHMAP_FR); sm->shift = tplc_chan_get_shift(tplg, mc->channel, sm->shift = tplg_chan_get_shift(tplg, mc->channel, SNDRV_CHMAP_FL); sm->rshift = tplc_chan_get_shift(tplg, mc->channel, sm->rshift = tplg_chan_get_shift(tplg, mc->channel, SNDRV_CHMAP_FR); sm->max = le32_to_cpu(mc->max); Loading @@ -1193,7 +1161,7 @@ static int soc_tplg_dapm_widget_dmixer_create(struct soc_tplg *tplg, struct snd_ } /* pass control to driver for optional further init */ err = soc_tplg_control_load(tplg, kc, (struct snd_soc_tplg_ctl_hdr *)mc); err = soc_tplg_control_load(tplg, kc, &mc->hdr); if (err < 0) { dev_err(tplg->dev, "ASoC: failed to init %s\n", mc->hdr.name); Loading Loading @@ -1233,10 +1201,10 @@ static int soc_tplg_dapm_widget_denum_create(struct soc_tplg *tplg, struct snd_k kc->access = le32_to_cpu(ec->hdr.access); /* we only support FL/FR channel mapping atm */ se->reg = tplc_chan_get_reg(tplg, ec->channel, SNDRV_CHMAP_FL); se->shift_l = tplc_chan_get_shift(tplg, ec->channel, se->reg = tplg_chan_get_reg(tplg, ec->channel, SNDRV_CHMAP_FL); se->shift_l = tplg_chan_get_shift(tplg, ec->channel, SNDRV_CHMAP_FL); se->shift_r = tplc_chan_get_shift(tplg, ec->channel, se->shift_r = tplg_chan_get_shift(tplg, ec->channel, SNDRV_CHMAP_FR); se->items = le32_to_cpu(ec->items); Loading Loading @@ -1277,7 +1245,7 @@ static int soc_tplg_dapm_widget_denum_create(struct soc_tplg *tplg, struct snd_k } /* pass control to driver for optional further init */ err = soc_tplg_control_load(tplg, kc, (struct snd_soc_tplg_ctl_hdr *)ec); err = soc_tplg_control_load(tplg, kc, &ec->hdr); if (err < 0) { dev_err(tplg->dev, "ASoC: failed to init %s\n", ec->hdr.name); Loading Loading @@ -1329,7 +1297,7 @@ static int soc_tplg_dapm_widget_dbytes_create(struct soc_tplg *tplg, struct snd_ } /* pass control to driver for optional further init */ err = soc_tplg_control_load(tplg, kc, (struct snd_soc_tplg_ctl_hdr *)be); err = soc_tplg_control_load(tplg, kc, &be->hdr); if (err < 0) { dev_err(tplg->dev, "ASoC: failed to init %s\n", be->hdr.name); Loading Loading @@ -1479,7 +1447,8 @@ static int soc_tplg_dapm_widget_create(struct soc_tplg *tplg, widget->dobj.type = SND_SOC_DOBJ_WIDGET; widget->dobj.widget.kcontrol_type = kcontrol_type; widget->dobj.ops = tplg->ops; if (tplg->ops) widget->dobj.unload = tplg->ops->widget_unload; widget->dobj.index = tplg->index; list_add(&widget->dobj.list, &tplg->comp->dobj_list); Loading @@ -1493,7 +1462,7 @@ static int soc_tplg_dapm_widget_create(struct soc_tplg *tplg, return 0; ready_err: remove_widget(widget->dapm->component, &widget->dobj, SOC_TPLG_PASS_WIDGET); soc_tplg_remove_widget(widget->dapm->component, &widget->dobj, SOC_TPLG_PASS_WIDGET); snd_soc_dapm_free_widget(widget); hdr_err: kfree(template.sname); Loading Loading @@ -1567,7 +1536,7 @@ static int soc_tplg_dapm_complete(struct soc_tplg *tplg) dev_err(tplg->dev, "ASoC: failed to create new widgets %d\n", ret); return 0; return ret; } static int set_stream_info(struct soc_tplg *tplg, struct snd_soc_pcm_stream *stream, Loading Loading @@ -1657,8 +1626,9 @@ static int soc_tplg_dai_create(struct soc_tplg *tplg, } dai_drv->dobj.index = tplg->index; dai_drv->dobj.ops = tplg->ops; dai_drv->dobj.type = SND_SOC_DOBJ_PCM; if (tplg->ops) dai_drv->dobj.unload = tplg->ops->dai_unload; list_add(&dai_drv->dobj.list, &tplg->comp->dobj_list); /* register the DAI to the component */ Loading Loading @@ -1727,8 +1697,9 @@ static int soc_tplg_fe_link_create(struct soc_tplg *tplg, link->num_platforms = 1; link->dobj.index = tplg->index; link->dobj.ops = tplg->ops; link->dobj.type = SND_SOC_DOBJ_DAI_LINK; if (tplg->ops) link->dobj.unload = tplg->ops->link_unload; if (strlen(pcm->pcm_name)) { link->name = devm_kstrdup(tplg->dev, pcm->pcm_name, GFP_KERNEL); Loading Loading @@ -2135,8 +2106,9 @@ static int soc_tplg_link_config(struct soc_tplg *tplg, /* for unloading it in snd_soc_tplg_component_remove */ link->dobj.index = tplg->index; link->dobj.ops = tplg->ops; link->dobj.type = SND_SOC_DOBJ_BACKEND_LINK; if (tplg->ops) link->dobj.unload = tplg->ops->link_unload; list_add(&link->dobj.list, &tplg->comp->dobj_list); return 0; Loading Loading @@ -2390,12 +2362,9 @@ static int soc_tplg_manifest_load(struct soc_tplg *tplg, } /* validate header magic, size and type */ static int soc_valid_header(struct soc_tplg *tplg, static int soc_tplg_valid_header(struct soc_tplg *tplg, struct snd_soc_tplg_hdr *hdr) { if (soc_tplg_get_hdr_offset(tplg) >= tplg->fw->size) return 0; if (le32_to_cpu(hdr->size) != sizeof(*hdr)) { dev_err(tplg->dev, "ASoC: invalid header size for type %d at offset 0x%lx size 0x%zx.\n", Loading @@ -2404,7 +2373,7 @@ static int soc_valid_header(struct soc_tplg *tplg, return -EINVAL; } if (soc_tplg_get_hdr_offset(tplg) + hdr->payload_size >= tplg->fw->size) { if (soc_tplg_get_hdr_offset(tplg) + le32_to_cpu(hdr->payload_size) >= tplg->fw->size) { dev_err(tplg->dev, "ASoC: invalid header of type %d at offset %ld payload_size %d\n", le32_to_cpu(hdr->type), soc_tplg_get_hdr_offset(tplg), Loading Loading @@ -2446,7 +2415,7 @@ static int soc_valid_header(struct soc_tplg *tplg, return -EINVAL; } return 1; return 0; } /* check header type and call appropriate handler */ Loading Loading @@ -2527,13 +2496,11 @@ static int soc_tplg_process_headers(struct soc_tplg *tplg) while (!soc_tplg_is_eof(tplg)) { /* make sure header is valid before loading */ ret = soc_valid_header(tplg, hdr); ret = soc_tplg_valid_header(tplg, hdr); if (ret < 0) { dev_err(tplg->dev, "ASoC: topology: invalid header: %d\n", ret); return ret; } else if (ret == 0) { break; } /* load the header object */ Loading Loading @@ -2627,26 +2594,22 @@ int snd_soc_tplg_component_remove(struct snd_soc_component *comp) list) { switch (dobj->type) { case SND_SOC_DOBJ_MIXER: remove_mixer(comp, dobj, pass); break; case SND_SOC_DOBJ_ENUM: remove_enum(comp, dobj, pass); break; case SND_SOC_DOBJ_BYTES: remove_bytes(comp, dobj, pass); case SND_SOC_DOBJ_ENUM: case SND_SOC_DOBJ_MIXER: soc_tplg_remove_kcontrol(comp, dobj, pass); break; case SND_SOC_DOBJ_GRAPH: remove_route(comp, dobj, pass); soc_tplg_remove_route(comp, dobj, pass); break; case SND_SOC_DOBJ_WIDGET: remove_widget(comp, dobj, pass); soc_tplg_remove_widget(comp, dobj, pass); break; case SND_SOC_DOBJ_PCM: remove_dai(comp, dobj, pass); soc_tplg_remove_dai(comp, dobj, pass); break; case SND_SOC_DOBJ_DAI_LINK: remove_link(comp, dobj, pass); soc_tplg_remove_link(comp, dobj, pass); break; case SND_SOC_DOBJ_BACKEND_LINK: /* Loading