in cirrus/cs_dsp.c [928:998]
static int cs_dsp_create_control(struct cs_dsp *dsp,
const struct cs_dsp_alg_region *alg_region,
unsigned int offset, unsigned int len,
const char *subname, unsigned int subname_len,
unsigned int flags, unsigned int type)
{
struct cs_dsp_coeff_ctl *ctl;
int ret;
list_for_each_entry(ctl, &dsp->ctl_list, list) {
if (ctl->fw_name == dsp->fw_name &&
ctl->alg_region.alg == alg_region->alg &&
ctl->alg_region.type == alg_region->type) {
if ((!subname && !ctl->subname) ||
(subname && !strncmp(ctl->subname, subname, ctl->subname_len))) {
if (!ctl->enabled)
ctl->enabled = 1;
return 0;
}
}
}
ctl = kzalloc(sizeof(*ctl), GFP_KERNEL);
if (!ctl)
return -ENOMEM;
ctl->fw_name = dsp->fw_name;
ctl->alg_region = *alg_region;
if (subname && dsp->fw_ver >= 2) {
ctl->subname_len = subname_len;
ctl->subname = kmemdup(subname,
strlen(subname) + 1, GFP_KERNEL);
if (!ctl->subname) {
ret = -ENOMEM;
goto err_ctl;
}
}
ctl->enabled = 1;
ctl->set = 0;
ctl->dsp = dsp;
ctl->flags = flags;
ctl->type = type;
ctl->offset = offset;
ctl->len = len;
ctl->cache = kzalloc(ctl->len, GFP_KERNEL);
if (!ctl->cache) {
ret = -ENOMEM;
goto err_ctl_subname;
}
list_add(&ctl->list, &dsp->ctl_list);
if (dsp->client_ops->control_add) {
ret = dsp->client_ops->control_add(ctl);
if (ret)
goto err_list_del;
}
return 0;
err_list_del:
list_del(&ctl->list);
kfree(ctl->cache);
err_ctl_subname:
kfree(ctl->subname);
err_ctl:
kfree(ctl);
return ret;
}