static int cs_dsp_create_control()

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;
}