|
|
|
@ -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,13 @@ 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;
|
|
|
|
|
|
|
|
|
|
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 +869,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 +881,18 @@ 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))
|
|
|
|
|
return -EINVAL;
|
|
|
|
|
|
|
|
|
|
se->dobj.control.dvalues = kzalloc(le32_to_cpu(ec->items) *
|
|
|
|
|
se->dobj.control.dvalues = devm_kzalloc(tplg->dev, le32_to_cpu(ec->items) *
|
|
|
|
|
sizeof(u32),
|
|
|
|
|
GFP_KERNEL);
|
|
|
|
|
if (!se->dobj.control.dvalues)
|
|
|
|
@ -1000,11 +906,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 +932,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 +963,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 +974,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 +1020,6 @@ static int soc_tplg_denum_create(struct soc_tplg *tplg, unsigned int count,
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
err_denum:
|
|
|
|
|
kfree(se);
|
|
|
|
|
return err;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -1196,7 +1096,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 +1125,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++) {
|
|
|
|
@ -1290,15 +1184,6 @@ static int soc_tplg_dapm_graph_elems_load(struct soc_tplg *tplg,
|
|
|
|
|
snd_soc_dapm_add_routes(dapm, routes[i], 1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* 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
|
|
|
|
@ -1317,7 +1202,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 +1214,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 +1225,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 +1275,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 +1286,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 +1297,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 +1308,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 +1328,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 +1338,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 +1371,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 +1382,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 +1394,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 +1406,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 +1435,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 +1582,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 +1641,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 +1688,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 +1704,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 +1712,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 +1723,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 +1733,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 +1747,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 +1782,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 +1801,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 +1811,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 +1835,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 +1849,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;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -2473,7 +2321,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 +2329,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 +2342,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 +2526,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 +2645,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 +2660,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 +2668,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 +2687,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);
|
|
|
|
|