diff options
Diffstat (limited to 'sound/soc/soc-topology.c')
-rw-r--r-- | sound/soc/soc-topology.c | 337 |
1 files changed, 73 insertions, 264 deletions
diff --git a/sound/soc/soc-topology.c b/sound/soc/soc-topology.c index c5ef432a023b..950c45008e24 100644 --- a/sound/soc/soc-topology.c +++ b/sound/soc/soc-topology.c @@ -64,7 +64,6 @@ struct soc_tplg { struct device *dev; struct snd_soc_component *comp; u32 index; /* current block index */ - u32 req_index; /* required index, only loaded/free matching blocks */ /* vendor specific kcontrol operations */ const struct snd_soc_tplg_kcontrol_ops *io_ops; @@ -80,8 +79,6 @@ struct soc_tplg { static int soc_tplg_process_headers(struct soc_tplg *tplg); static void soc_tplg_complete(struct soc_tplg *tplg); -static void soc_tplg_denum_remove_texts(struct soc_enum *se); -static void soc_tplg_denum_remove_values(struct soc_enum *se); /* 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, @@ -360,9 +357,6 @@ static void remove_mixer(struct snd_soc_component *comp, struct snd_soc_dobj *dobj, int pass) { struct snd_card *card = comp->card->snd_card; - struct soc_mixer_control *sm = - container_of(dobj, struct soc_mixer_control, dobj); - const unsigned int *p = NULL; if (pass != SOC_TPLG_PASS_MIXER) return; @@ -370,12 +364,8 @@ static void remove_mixer(struct snd_soc_component *comp, if (dobj->ops && dobj->ops->control_unload) dobj->ops->control_unload(comp, dobj); - if (dobj->control.kcontrol->tlv.p) - p = dobj->control.kcontrol->tlv.p; snd_ctl_remove(card, dobj->control.kcontrol); list_del(&dobj->list); - kfree(sm); - kfree(p); } /* remove an enum kcontrol */ @@ -383,7 +373,6 @@ static void remove_enum(struct snd_soc_component *comp, struct snd_soc_dobj *dobj, int pass) { struct snd_card *card = comp->card->snd_card; - struct soc_enum *se = container_of(dobj, struct soc_enum, dobj); if (pass != SOC_TPLG_PASS_MIXER) return; @@ -393,10 +382,6 @@ static void remove_enum(struct snd_soc_component *comp, snd_ctl_remove(card, dobj->control.kcontrol); list_del(&dobj->list); - - soc_tplg_denum_remove_values(se); - soc_tplg_denum_remove_texts(se); - kfree(se); } /* remove a byte kcontrol */ @@ -404,8 +389,6 @@ static void remove_bytes(struct snd_soc_component *comp, struct snd_soc_dobj *dobj, int pass) { struct snd_card *card = comp->card->snd_card; - struct soc_bytes_ext *sb = - container_of(dobj, struct soc_bytes_ext, dobj); if (pass != SOC_TPLG_PASS_MIXER) return; @@ -415,16 +398,12 @@ static void remove_bytes(struct snd_soc_component *comp, snd_ctl_remove(card, dobj->control.kcontrol); list_del(&dobj->list); - kfree(sb); } /* remove a route */ static void remove_route(struct snd_soc_component *comp, struct snd_soc_dobj *dobj, int pass) { - struct snd_soc_dapm_route *route = - container_of(dobj, struct snd_soc_dapm_route, dobj); - if (pass != SOC_TPLG_PASS_GRAPH) return; @@ -432,7 +411,6 @@ static void remove_route(struct snd_soc_component *comp, dobj->ops->dapm_route_unload(comp, dobj); list_del(&dobj->list); - kfree(route); } /* remove a widget and it's kcontrols - routes must be removed first */ @@ -453,47 +431,10 @@ static void remove_widget(struct snd_soc_component *comp, if (!w->kcontrols) goto free_news; - /* - * Dynamic Widgets either have 1..N enum kcontrols or mixers. - * The enum may either have an array of values or strings. - */ - if (dobj->widget.kcontrol_type == SND_SOC_TPLG_TYPE_ENUM) { - /* enumerated widget mixer */ - for (i = 0; w->kcontrols != NULL && i < w->num_kcontrols; i++) { - struct snd_kcontrol *kcontrol = w->kcontrols[i]; - struct soc_enum *se = - (struct soc_enum *)kcontrol->private_value; - - snd_ctl_remove(card, kcontrol); - - /* free enum kcontrol's dvalues and dtexts */ - soc_tplg_denum_remove_values(se); - soc_tplg_denum_remove_texts(se); - - kfree(se); - kfree(w->kcontrol_news[i].name); - } - } else { - /* volume mixer or bytes controls */ - for (i = 0; w->kcontrols != NULL && i < w->num_kcontrols; i++) { - struct snd_kcontrol *kcontrol = w->kcontrols[i]; - - if (dobj->widget.kcontrol_type - == SND_SOC_TPLG_TYPE_MIXER) - kfree(kcontrol->tlv.p); - - /* Private value is used as struct soc_mixer_control - * for volume mixers or soc_bytes_ext for bytes - * controls. - */ - kfree((void *)kcontrol->private_value); - snd_ctl_remove(card, kcontrol); - kfree(w->kcontrol_news[i].name); - } - } + for (i = 0; w->kcontrols && i < w->num_kcontrols; i++) + snd_ctl_remove(card, w->kcontrols[i]); free_news: - kfree(w->kcontrol_news); list_del(&dobj->list); @@ -518,11 +459,7 @@ static void remove_dai(struct snd_soc_component *comp, if (dai->driver == dai_drv) dai->driver = NULL; - kfree(dai_drv->playback.stream_name); - kfree(dai_drv->capture.stream_name); - kfree(dai_drv->name); list_del(&dobj->list); - kfree(dai_drv); } /* remove link configurations */ @@ -541,11 +478,6 @@ static void remove_link(struct snd_soc_component *comp, list_del(&dobj->list); snd_soc_remove_pcm_runtime(comp->card, snd_soc_get_pcm_runtime(comp->card, link)); - - kfree(link->name); - kfree(link->stream_name); - kfree(link->cpus->dai_name); - kfree(link); } /* unload dai link */ @@ -700,7 +632,7 @@ static int soc_tplg_create_tlv_db_scale(struct soc_tplg *tplg, unsigned int item_len = 2 * sizeof(unsigned int); unsigned int *p; - p = kzalloc(item_len + 2 * sizeof(unsigned int), GFP_KERNEL); + p = devm_kzalloc(tplg->dev, item_len + 2 * sizeof(unsigned int), GFP_KERNEL); if (!p) return -ENOMEM; @@ -741,12 +673,6 @@ static int soc_tplg_create_tlv(struct soc_tplg *tplg, return 0; } -static inline void soc_tplg_free_tlv(struct soc_tplg *tplg, - struct snd_kcontrol_new *kc) -{ - kfree(kc->tlv.p); -} - static int soc_tplg_dbytes_create(struct soc_tplg *tplg, unsigned int count, size_t size) { @@ -772,7 +698,7 @@ static int soc_tplg_dbytes_create(struct soc_tplg *tplg, unsigned int count, SNDRV_CTL_ELEM_ID_NAME_MAXLEN) return -EINVAL; - sbe = kzalloc(sizeof(*sbe), GFP_KERNEL); + sbe = devm_kzalloc(tplg->dev, sizeof(*sbe), GFP_KERNEL); if (sbe == NULL) return -ENOMEM; @@ -798,7 +724,6 @@ static int soc_tplg_dbytes_create(struct soc_tplg *tplg, unsigned int count, err = soc_tplg_kcontrol_bind_io(&be->hdr, &kc, tplg); if (err) { soc_control_err(tplg, &be->hdr, be->hdr.name); - kfree(sbe); break; } @@ -808,7 +733,6 @@ static int soc_tplg_dbytes_create(struct soc_tplg *tplg, unsigned int count, if (err < 0) { dev_err(tplg->dev, "ASoC: failed to init %s\n", be->hdr.name); - kfree(sbe); break; } @@ -818,7 +742,6 @@ static int soc_tplg_dbytes_create(struct soc_tplg *tplg, unsigned int count, if (err < 0) { dev_err(tplg->dev, "ASoC: failed to add %s\n", be->hdr.name); - kfree(sbe); break; } @@ -854,7 +777,7 @@ static int soc_tplg_dmixer_create(struct soc_tplg *tplg, unsigned int count, SNDRV_CTL_ELEM_ID_NAME_MAXLEN) return -EINVAL; - sm = kzalloc(sizeof(*sm), GFP_KERNEL); + sm = devm_kzalloc(tplg->dev, sizeof(*sm), GFP_KERNEL); if (sm == NULL) return -ENOMEM; tplg->pos += (sizeof(struct snd_soc_tplg_mixer_control) + @@ -893,7 +816,6 @@ static int soc_tplg_dmixer_create(struct soc_tplg *tplg, unsigned int count, err = soc_tplg_kcontrol_bind_io(&mc->hdr, &kc, tplg); if (err) { soc_control_err(tplg, &mc->hdr, mc->hdr.name); - kfree(sm); break; } @@ -902,7 +824,6 @@ static int soc_tplg_dmixer_create(struct soc_tplg *tplg, unsigned int count, if (err < 0) { dev_err(tplg->dev, "ASoC: failed to create TLV %s\n", mc->hdr.name); - kfree(sm); break; } @@ -912,8 +833,6 @@ static int soc_tplg_dmixer_create(struct soc_tplg *tplg, unsigned int count, if (err < 0) { dev_err(tplg->dev, "ASoC: failed to init %s\n", mc->hdr.name); - soc_tplg_free_tlv(tplg, &kc); - kfree(sm); break; } @@ -923,8 +842,6 @@ static int soc_tplg_dmixer_create(struct soc_tplg *tplg, unsigned int count, if (err < 0) { dev_err(tplg->dev, "ASoC: failed to add %s\n", mc->hdr.name); - soc_tplg_free_tlv(tplg, &kc); - kfree(sm); break; } @@ -934,13 +851,16 @@ static int soc_tplg_dmixer_create(struct soc_tplg *tplg, unsigned int count, return err; } -static int soc_tplg_denum_create_texts(struct soc_enum *se, - struct snd_soc_tplg_enum_control *ec) +static int soc_tplg_denum_create_texts(struct soc_tplg *tplg, struct soc_enum *se, + struct snd_soc_tplg_enum_control *ec) { int i, ret; + if (le32_to_cpu(ec->items) > ARRAY_SIZE(ec->texts)) + return -EINVAL; + se->dobj.control.dtexts = - kcalloc(le32_to_cpu(ec->items), sizeof(char *), GFP_KERNEL); + devm_kcalloc(tplg->dev, le32_to_cpu(ec->items), sizeof(char *), GFP_KERNEL); if (se->dobj.control.dtexts == NULL) return -ENOMEM; @@ -952,7 +872,7 @@ static int soc_tplg_denum_create_texts(struct soc_enum *se, goto err; } - se->dobj.control.dtexts[i] = kstrdup(ec->texts[i], GFP_KERNEL); + se->dobj.control.dtexts[i] = devm_kstrdup(tplg->dev, ec->texts[i], GFP_KERNEL); if (!se->dobj.control.dtexts[i]) { ret = -ENOMEM; goto err; @@ -964,29 +884,24 @@ static int soc_tplg_denum_create_texts(struct soc_enum *se, return 0; err: - se->items = i; - soc_tplg_denum_remove_texts(se); return ret; } -static inline void soc_tplg_denum_remove_texts(struct soc_enum *se) -{ - int i = se->items; - - for (--i; i >= 0; i--) - kfree(se->dobj.control.dtexts[i]); - kfree(se->dobj.control.dtexts); -} - -static int soc_tplg_denum_create_values(struct soc_enum *se, - struct snd_soc_tplg_enum_control *ec) +static int soc_tplg_denum_create_values(struct soc_tplg *tplg, struct soc_enum *se, + struct snd_soc_tplg_enum_control *ec) { int i; - if (le32_to_cpu(ec->items) > sizeof(*ec->values)) + /* + * Following "if" checks if we have at most SND_SOC_TPLG_NUM_TEXTS + * values instead of using ARRAY_SIZE(ec->values) due to the fact that + * it is oversized for its purpose. Additionally it is done so because + * it is defined in UAPI header where it can't be easily changed. + */ + if (le32_to_cpu(ec->items) > SND_SOC_TPLG_NUM_TEXTS) return -EINVAL; - se->dobj.control.dvalues = kzalloc(le32_to_cpu(ec->items) * + se->dobj.control.dvalues = devm_kcalloc(tplg->dev, le32_to_cpu(ec->items), sizeof(u32), GFP_KERNEL); if (!se->dobj.control.dvalues) @@ -1000,11 +915,6 @@ static int soc_tplg_denum_create_values(struct soc_enum *se, return 0; } -static inline void soc_tplg_denum_remove_values(struct soc_enum *se) -{ - kfree(se->dobj.control.dvalues); -} - static int soc_tplg_denum_create(struct soc_tplg *tplg, unsigned int count, size_t size) { @@ -1031,7 +941,7 @@ static int soc_tplg_denum_create(struct soc_tplg *tplg, unsigned int count, SNDRV_CTL_ELEM_ID_NAME_MAXLEN) return -EINVAL; - se = kzalloc((sizeof(*se)), GFP_KERNEL); + se = devm_kzalloc(tplg->dev, (sizeof(*se)), GFP_KERNEL); if (se == NULL) return -ENOMEM; @@ -1062,7 +972,7 @@ static int soc_tplg_denum_create(struct soc_tplg *tplg, unsigned int count, switch (le32_to_cpu(ec->hdr.ops.info)) { case SND_SOC_TPLG_DAPM_CTL_ENUM_VALUE: case SND_SOC_TPLG_CTL_ENUM_VALUE: - err = soc_tplg_denum_create_values(se, ec); + err = soc_tplg_denum_create_values(tplg, se, ec); if (err < 0) { dev_err(tplg->dev, "ASoC: could not create values for %s\n", @@ -1073,7 +983,7 @@ static int soc_tplg_denum_create(struct soc_tplg *tplg, unsigned int count, case SND_SOC_TPLG_CTL_ENUM: case SND_SOC_TPLG_DAPM_CTL_ENUM_DOUBLE: case SND_SOC_TPLG_DAPM_CTL_ENUM_VIRT: - err = soc_tplg_denum_create_texts(se, ec); + err = soc_tplg_denum_create_texts(tplg, se, ec); if (err < 0) { dev_err(tplg->dev, "ASoC: could not create texts for %s\n", @@ -1119,7 +1029,6 @@ static int soc_tplg_denum_create(struct soc_tplg *tplg, unsigned int count, return 0; err_denum: - kfree(se); return err; } @@ -1196,7 +1105,7 @@ static int soc_tplg_dapm_graph_elems_load(struct soc_tplg *tplg, struct snd_soc_dapm_context *dapm = &tplg->comp->dapm; struct snd_soc_tplg_dapm_graph_elem *elem; struct snd_soc_dapm_route **routes; - int count, i, j; + int count, i; int ret = 0; count = le32_to_cpu(hdr->count); @@ -1225,15 +1134,9 @@ static int soc_tplg_dapm_graph_elems_load(struct soc_tplg *tplg, * each route can be freed when it is removed in remove_route(). */ for (i = 0; i < count; i++) { - routes[i] = kzalloc(sizeof(*routes[i]), GFP_KERNEL); - if (!routes[i]) { - /* free previously allocated memory */ - for (j = 0; j < i; j++) - kfree(routes[j]); - - kfree(routes); + routes[i] = devm_kzalloc(tplg->dev, sizeof(*routes[i]), GFP_KERNEL); + if (!routes[i]) return -ENOMEM; - } } for (i = 0; i < count; i++) { @@ -1291,15 +1194,6 @@ static int soc_tplg_dapm_graph_elems_load(struct soc_tplg *tplg, } /* - * free memory allocated for all dapm routes not added to the - * list in case of error - */ - if (ret < 0) { - while (i < count) - kfree(routes[i++]); - } - - /* * free pointer to array of dapm routes as this is no longer needed. * The memory allocated for each dapm route will be freed * when it is removed in remove_route(). @@ -1317,7 +1211,7 @@ static struct snd_kcontrol_new *soc_tplg_dapm_widget_dmixer_create( struct snd_soc_tplg_mixer_control *mc; int i, err; - kc = kcalloc(num_kcontrols, sizeof(*kc), GFP_KERNEL); + kc = devm_kcalloc(tplg->dev, num_kcontrols, sizeof(*kc), GFP_KERNEL); if (kc == NULL) return NULL; @@ -1329,7 +1223,7 @@ static struct snd_kcontrol_new *soc_tplg_dapm_widget_dmixer_create( SNDRV_CTL_ELEM_ID_NAME_MAXLEN) goto err_sm; - sm = kzalloc(sizeof(*sm), GFP_KERNEL); + sm = devm_kzalloc(tplg->dev, sizeof(*sm), GFP_KERNEL); if (sm == NULL) goto err_sm; @@ -1340,7 +1234,7 @@ static struct snd_kcontrol_new *soc_tplg_dapm_widget_dmixer_create( mc->hdr.name, i); kc[i].private_value = (long)sm; - kc[i].name = kstrdup(mc->hdr.name, GFP_KERNEL); + kc[i].name = devm_kstrdup(tplg->dev, mc->hdr.name, GFP_KERNEL); if (kc[i].name == NULL) goto err_sm; kc[i].iface = SNDRV_CTL_ELEM_IFACE_MIXER; @@ -1390,14 +1284,6 @@ static struct snd_kcontrol_new *soc_tplg_dapm_widget_dmixer_create( return kc; err_sm: - for (; i >= 0; i--) { - soc_tplg_free_tlv(tplg, &kc[i]); - sm = (struct soc_mixer_control *)kc[i].private_value; - kfree(sm); - kfree(kc[i].name); - } - kfree(kc); - return NULL; } @@ -1409,7 +1295,7 @@ static struct snd_kcontrol_new *soc_tplg_dapm_widget_denum_create( struct soc_enum *se; int i, err; - kc = kcalloc(num_kcontrols, sizeof(*kc), GFP_KERNEL); + kc = devm_kcalloc(tplg->dev, num_kcontrols, sizeof(*kc), GFP_KERNEL); if (kc == NULL) return NULL; @@ -1420,7 +1306,7 @@ static struct snd_kcontrol_new *soc_tplg_dapm_widget_denum_create( SNDRV_CTL_ELEM_ID_NAME_MAXLEN) goto err_se; - se = kzalloc(sizeof(*se), GFP_KERNEL); + se = devm_kzalloc(tplg->dev, sizeof(*se), GFP_KERNEL); if (se == NULL) goto err_se; @@ -1431,7 +1317,7 @@ static struct snd_kcontrol_new *soc_tplg_dapm_widget_denum_create( ec->hdr.name); kc[i].private_value = (long)se; - kc[i].name = kstrdup(ec->hdr.name, GFP_KERNEL); + kc[i].name = devm_kstrdup(tplg->dev, ec->hdr.name, GFP_KERNEL); if (kc[i].name == NULL) goto err_se; kc[i].iface = SNDRV_CTL_ELEM_IFACE_MIXER; @@ -1451,7 +1337,7 @@ static struct snd_kcontrol_new *soc_tplg_dapm_widget_denum_create( switch (le32_to_cpu(ec->hdr.ops.info)) { case SND_SOC_TPLG_CTL_ENUM_VALUE: case SND_SOC_TPLG_DAPM_CTL_ENUM_VALUE: - err = soc_tplg_denum_create_values(se, ec); + err = soc_tplg_denum_create_values(tplg, se, ec); if (err < 0) { dev_err(tplg->dev, "ASoC: could not create values for %s\n", ec->hdr.name); @@ -1461,7 +1347,7 @@ static struct snd_kcontrol_new *soc_tplg_dapm_widget_denum_create( case SND_SOC_TPLG_CTL_ENUM: case SND_SOC_TPLG_DAPM_CTL_ENUM_DOUBLE: case SND_SOC_TPLG_DAPM_CTL_ENUM_VIRT: - err = soc_tplg_denum_create_texts(se, ec); + err = soc_tplg_denum_create_texts(tplg, se, ec); if (err < 0) { dev_err(tplg->dev, "ASoC: could not create texts for %s\n", ec->hdr.name); @@ -1494,20 +1380,6 @@ static struct snd_kcontrol_new *soc_tplg_dapm_widget_denum_create( return kc; err_se: - for (; i >= 0; i--) { - /* free values and texts */ - se = (struct soc_enum *)kc[i].private_value; - - if (se) { - soc_tplg_denum_remove_values(se); - soc_tplg_denum_remove_texts(se); - } - - kfree(se); - kfree(kc[i].name); - } - kfree(kc); - return NULL; } @@ -1519,7 +1391,7 @@ static struct snd_kcontrol_new *soc_tplg_dapm_widget_dbytes_create( struct snd_kcontrol_new *kc; int i, err; - kc = kcalloc(num_kcontrols, sizeof(*kc), GFP_KERNEL); + kc = devm_kcalloc(tplg->dev, num_kcontrols, sizeof(*kc), GFP_KERNEL); if (!kc) return NULL; @@ -1531,7 +1403,7 @@ static struct snd_kcontrol_new *soc_tplg_dapm_widget_dbytes_create( SNDRV_CTL_ELEM_ID_NAME_MAXLEN) goto err_sbe; - sbe = kzalloc(sizeof(*sbe), GFP_KERNEL); + sbe = devm_kzalloc(tplg->dev, sizeof(*sbe), GFP_KERNEL); if (sbe == NULL) goto err_sbe; @@ -1543,7 +1415,7 @@ static struct snd_kcontrol_new *soc_tplg_dapm_widget_dbytes_create( be->hdr.name, be->hdr.access); kc[i].private_value = (long)sbe; - kc[i].name = kstrdup(be->hdr.name, GFP_KERNEL); + kc[i].name = devm_kstrdup(tplg->dev, be->hdr.name, GFP_KERNEL); if (kc[i].name == NULL) goto err_sbe; kc[i].iface = SNDRV_CTL_ELEM_IFACE_MIXER; @@ -1572,12 +1444,6 @@ static struct snd_kcontrol_new *soc_tplg_dapm_widget_dbytes_create( return kc; err_sbe: - for (; i >= 0; i--) { - sbe = (struct soc_bytes_ext *)kc[i].private_value; - kfree(sbe); - kfree(kc[i].name); - } - kfree(kc); return NULL; } @@ -1725,7 +1591,7 @@ widget: return 0; ready_err: - snd_soc_tplg_widget_remove(widget); + remove_widget(widget->dapm->component, &widget->dobj, SOC_TPLG_PASS_WIDGET); snd_soc_dapm_free_widget(widget); hdr_err: kfree(template.sname); @@ -1784,10 +1650,10 @@ static int soc_tplg_dapm_complete(struct soc_tplg *tplg) return 0; } -static int set_stream_info(struct snd_soc_pcm_stream *stream, - struct snd_soc_tplg_stream_caps *caps) +static int set_stream_info(struct soc_tplg *tplg, struct snd_soc_pcm_stream *stream, + struct snd_soc_tplg_stream_caps *caps) { - stream->stream_name = kstrdup(caps->name, GFP_KERNEL); + stream->stream_name = devm_kstrdup(tplg->dev, caps->name, GFP_KERNEL); if (!stream->stream_name) return -ENOMEM; @@ -1831,12 +1697,12 @@ static int soc_tplg_dai_create(struct soc_tplg *tplg, snd_soc_component_get_dapm(tplg->comp); int ret; - dai_drv = kzalloc(sizeof(struct snd_soc_dai_driver), GFP_KERNEL); + dai_drv = devm_kzalloc(tplg->dev, sizeof(struct snd_soc_dai_driver), GFP_KERNEL); if (dai_drv == NULL) return -ENOMEM; if (strlen(pcm->dai_name)) { - dai_drv->name = kstrdup(pcm->dai_name, GFP_KERNEL); + dai_drv->name = devm_kstrdup(tplg->dev, pcm->dai_name, GFP_KERNEL); if (!dai_drv->name) { ret = -ENOMEM; goto err; @@ -1847,7 +1713,7 @@ static int soc_tplg_dai_create(struct soc_tplg *tplg, if (pcm->playback) { stream = &dai_drv->playback; caps = &pcm->caps[SND_SOC_TPLG_STREAM_PLAYBACK]; - ret = set_stream_info(stream, caps); + ret = set_stream_info(tplg, stream, caps); if (ret < 0) goto err; } @@ -1855,7 +1721,7 @@ static int soc_tplg_dai_create(struct soc_tplg *tplg, if (pcm->capture) { stream = &dai_drv->capture; caps = &pcm->caps[SND_SOC_TPLG_STREAM_CAPTURE]; - ret = set_stream_info(stream, caps); + ret = set_stream_info(tplg, stream, caps); if (ret < 0) goto err; } @@ -1866,7 +1732,7 @@ static int soc_tplg_dai_create(struct soc_tplg *tplg, /* pass control to component driver for optional further init */ ret = soc_tplg_dai_load(tplg, dai_drv, pcm, NULL); if (ret < 0) { - dev_err(tplg->comp->dev, "ASoC: DAI loading failed\n"); + dev_err(tplg->dev, "ASoC: DAI loading failed\n"); goto err; } @@ -1876,7 +1742,7 @@ static int soc_tplg_dai_create(struct soc_tplg *tplg, list_add(&dai_drv->dobj.list, &tplg->comp->dobj_list); /* register the DAI to the component */ - dai = devm_snd_soc_register_dai(tplg->comp->dev, tplg->comp, dai_drv, false); + dai = devm_snd_soc_register_dai(tplg->dev, tplg->comp, dai_drv, false); if (!dai) return -ENOMEM; @@ -1890,11 +1756,6 @@ static int soc_tplg_dai_create(struct soc_tplg *tplg, return 0; err: - kfree(dai_drv->playback.stream_name); - kfree(dai_drv->capture.stream_name); - kfree(dai_drv->name); - kfree(dai_drv); - return ret; } @@ -1930,7 +1791,7 @@ static int soc_tplg_fe_link_create(struct soc_tplg *tplg, int ret; /* link + cpu + codec + platform */ - link = kzalloc(sizeof(*link) + (3 * sizeof(*dlc)), GFP_KERNEL); + link = devm_kzalloc(tplg->dev, sizeof(*link) + (3 * sizeof(*dlc)), GFP_KERNEL); if (link == NULL) return -ENOMEM; @@ -1949,8 +1810,8 @@ static int soc_tplg_fe_link_create(struct soc_tplg *tplg, link->dobj.type = SND_SOC_DOBJ_DAI_LINK; if (strlen(pcm->pcm_name)) { - link->name = kstrdup(pcm->pcm_name, GFP_KERNEL); - link->stream_name = kstrdup(pcm->pcm_name, GFP_KERNEL); + link->name = devm_kstrdup(tplg->dev, pcm->pcm_name, GFP_KERNEL); + link->stream_name = devm_kstrdup(tplg->dev, pcm->pcm_name, GFP_KERNEL); if (!link->name || !link->stream_name) { ret = -ENOMEM; goto err; @@ -1959,7 +1820,7 @@ static int soc_tplg_fe_link_create(struct soc_tplg *tplg, link->id = le32_to_cpu(pcm->pcm_id); if (strlen(pcm->dai_name)) { - link->cpus->dai_name = kstrdup(pcm->dai_name, GFP_KERNEL); + link->cpus->dai_name = devm_kstrdup(tplg->dev, pcm->dai_name, GFP_KERNEL); if (!link->cpus->dai_name) { ret = -ENOMEM; goto err; @@ -1983,13 +1844,13 @@ static int soc_tplg_fe_link_create(struct soc_tplg *tplg, /* pass control to component driver for optional further init */ ret = soc_tplg_dai_link_load(tplg, link, NULL); if (ret < 0) { - dev_err(tplg->comp->dev, "ASoC: FE link loading failed\n"); + dev_err(tplg->dev, "ASoC: FE link loading failed\n"); goto err; } ret = snd_soc_add_pcm_runtime(tplg->comp->card, link); if (ret < 0) { - dev_err(tplg->comp->dev, "ASoC: adding FE link failed\n"); + dev_err(tplg->dev, "ASoC: adding FE link failed\n"); goto err; } @@ -1997,10 +1858,6 @@ static int soc_tplg_fe_link_create(struct soc_tplg *tplg, return 0; err: - kfree(link->name); - kfree(link->stream_name); - kfree(link->cpus->dai_name); - kfree(link); return ret; } @@ -2169,7 +2026,7 @@ static void set_link_hw_format(struct snd_soc_dai_link *link, struct snd_soc_tplg_link_config *cfg) { struct snd_soc_tplg_hw_config *hw_config; - unsigned char bclk_master, fsync_master; + unsigned char bclk_provider, fsync_provider; unsigned char invert_bclk, invert_fsync; int i; @@ -2209,18 +2066,18 @@ static void set_link_hw_format(struct snd_soc_dai_link *link, link->dai_fmt |= SND_SOC_DAIFMT_IB_IF; /* clock masters */ - bclk_master = (hw_config->bclk_master == - SND_SOC_TPLG_BCLK_CM); - fsync_master = (hw_config->fsync_master == - SND_SOC_TPLG_FSYNC_CM); - if (bclk_master && fsync_master) - link->dai_fmt |= SND_SOC_DAIFMT_CBM_CFM; - else if (!bclk_master && fsync_master) - link->dai_fmt |= SND_SOC_DAIFMT_CBS_CFM; - else if (bclk_master && !fsync_master) - link->dai_fmt |= SND_SOC_DAIFMT_CBM_CFS; + bclk_provider = (hw_config->bclk_provider == + SND_SOC_TPLG_BCLK_CP); + fsync_provider = (hw_config->fsync_provider == + SND_SOC_TPLG_FSYNC_CP); + if (bclk_provider && fsync_provider) + link->dai_fmt |= SND_SOC_DAIFMT_CBP_CFP; + else if (!bclk_provider && fsync_provider) + link->dai_fmt |= SND_SOC_DAIFMT_CBC_CFP; + else if (bclk_provider && !fsync_provider) + link->dai_fmt |= SND_SOC_DAIFMT_CBP_CFC; else - link->dai_fmt |= SND_SOC_DAIFMT_CBS_CFS; + link->dai_fmt |= SND_SOC_DAIFMT_CBC_CFC; } } @@ -2473,7 +2330,7 @@ static int soc_tplg_dai_config(struct soc_tplg *tplg, if (d->playback) { stream = &dai_drv->playback; caps = &d->caps[SND_SOC_TPLG_STREAM_PLAYBACK]; - ret = set_stream_info(stream, caps); + ret = set_stream_info(tplg, stream, caps); if (ret < 0) goto err; } @@ -2481,7 +2338,7 @@ static int soc_tplg_dai_config(struct soc_tplg *tplg, if (d->capture) { stream = &dai_drv->capture; caps = &d->caps[SND_SOC_TPLG_STREAM_CAPTURE]; - ret = set_stream_info(stream, caps); + ret = set_stream_info(tplg, stream, caps); if (ret < 0) goto err; } @@ -2494,15 +2351,13 @@ static int soc_tplg_dai_config(struct soc_tplg *tplg, /* pass control to component driver for optional further init */ ret = soc_tplg_dai_load(tplg, dai_drv, NULL, dai); if (ret < 0) { - dev_err(tplg->comp->dev, "ASoC: DAI loading failed\n"); + dev_err(tplg->dev, "ASoC: DAI loading failed\n"); goto err; } return 0; err: - kfree(dai_drv->playback.stream_name); - kfree(dai_drv->capture.stream_name); return ret; } @@ -2680,11 +2535,6 @@ static int soc_tplg_load_header(struct soc_tplg *tplg, tplg->pos = tplg->hdr_pos + sizeof(struct snd_soc_tplg_hdr); - /* check for matching ID */ - if (le32_to_cpu(hdr->index) != tplg->req_index && - tplg->req_index != SND_SOC_TPLG_INDEX_ALL) - return 0; - tplg->index = le32_to_cpu(hdr->index); switch (le32_to_cpu(hdr->type)) { @@ -2804,7 +2654,7 @@ static int soc_tplg_load(struct soc_tplg *tplg) /* load audio component topology from "firmware" file */ int snd_soc_tplg_component_load(struct snd_soc_component *comp, - struct snd_soc_tplg_ops *ops, const struct firmware *fw, u32 id) + struct snd_soc_tplg_ops *ops, const struct firmware *fw) { struct soc_tplg tplg; int ret; @@ -2819,7 +2669,6 @@ int snd_soc_tplg_component_load(struct snd_soc_component *comp, tplg.dev = comp->dev; tplg.comp = comp; tplg.ops = ops; - tplg.req_index = id; tplg.io_ops = ops->io_ops; tplg.io_ops_count = ops->io_ops_count; tplg.bytes_ext_ops = ops->bytes_ext_ops; @@ -2828,49 +2677,14 @@ int snd_soc_tplg_component_load(struct snd_soc_component *comp, ret = soc_tplg_load(&tplg); /* free the created components if fail to load topology */ if (ret) - snd_soc_tplg_component_remove(comp, SND_SOC_TPLG_INDEX_ALL); + snd_soc_tplg_component_remove(comp); return ret; } EXPORT_SYMBOL_GPL(snd_soc_tplg_component_load); -/* remove this dynamic widget */ -void snd_soc_tplg_widget_remove(struct snd_soc_dapm_widget *w) -{ - /* make sure we are a widget */ - if (w->dobj.type != SND_SOC_DOBJ_WIDGET) - return; - - remove_widget(w->dapm->component, &w->dobj, SOC_TPLG_PASS_WIDGET); -} -EXPORT_SYMBOL_GPL(snd_soc_tplg_widget_remove); - -/* remove all dynamic widgets from this DAPM context */ -void snd_soc_tplg_widget_remove_all(struct snd_soc_dapm_context *dapm, - u32 index) -{ - struct snd_soc_dapm_widget *w, *next_w; - - for_each_card_widgets_safe(dapm->card, w, next_w) { - - /* make sure we are a widget with correct context */ - if (w->dobj.type != SND_SOC_DOBJ_WIDGET || w->dapm != dapm) - continue; - - /* match ID */ - if (w->dobj.index != index && - w->dobj.index != SND_SOC_TPLG_INDEX_ALL) - continue; - /* check and free and dynamic widget kcontrols */ - snd_soc_tplg_widget_remove(w); - snd_soc_dapm_free_widget(w); - } - snd_soc_dapm_reset_cache(dapm); -} -EXPORT_SYMBOL_GPL(snd_soc_tplg_widget_remove_all); - /* remove dynamic controls from the component driver */ -int snd_soc_tplg_component_remove(struct snd_soc_component *comp, u32 index) +int snd_soc_tplg_component_remove(struct snd_soc_component *comp) { struct snd_soc_dobj *dobj, *next_dobj; int pass = SOC_TPLG_PASS_END; @@ -2882,11 +2696,6 @@ int snd_soc_tplg_component_remove(struct snd_soc_component *comp, u32 index) list_for_each_entry_safe(dobj, next_dobj, &comp->dobj_list, list) { - /* match index */ - if (dobj->index != index && - index != SND_SOC_TPLG_INDEX_ALL) - continue; - switch (dobj->type) { case SND_SOC_DOBJ_MIXER: remove_mixer(comp, dobj, pass); |