diff mbox series

[10/16] ASoC: wm_adsp: Separate generic cs_dsp_coeff_ctl handling

Message ID 20210913160057.103842-11-simont@opensource.cirrus.com (mailing list archive)
State Accepted
Commit 0700bc2fb94c28459f57a10d2ee2c7ef4cb70862
Headers show
Series add driver to support firmware loading on Cirrus Logic DSPs | expand

Commit Message

Simon Trimmer Sept. 13, 2021, 4 p.m. UTC
This is preparation for moving the generic DSP support out of ASoC. The
majority of the handling of firmware controls is generic and this change
separates the generic and ASoC specific details into separate structures
and functions and renames the generic code named wm_* to cs_*.

Signed-off-by: Simon Trimmer <simont@opensource.cirrus.com>
Signed-off-by: Charles Keepax <ckeepax@opensource.cirrus.com>
---
 sound/soc/codecs/wm_adsp.c | 283 ++++++++++++++++++++-----------------
 sound/soc/codecs/wm_adsp.h |  20 +++
 2 files changed, 176 insertions(+), 127 deletions(-)
diff mbox series

Patch

diff --git a/sound/soc/codecs/wm_adsp.c b/sound/soc/codecs/wm_adsp.c
index 82038cac4286..bd335e4240e5 100644
--- a/sound/soc/codecs/wm_adsp.c
+++ b/sound/soc/codecs/wm_adsp.c
@@ -607,21 +607,8 @@  static const struct {
 
 struct wm_coeff_ctl {
 	const char *name;
-	const char *fw_name;
-	/* Subname is needed to match with firmware */
-	const char *subname;
-	unsigned int subname_len;
-	struct cs_dsp_alg_region alg_region;
-	struct wm_adsp *dsp;
-	unsigned int enabled:1;
-	struct list_head list;
-	void *cache;
-	unsigned int offset;
-	size_t len;
-	unsigned int set:1;
+	struct cs_dsp_coeff_ctl *cs_ctl;
 	struct soc_bytes_ext bytes_ext;
-	unsigned int flags;
-	unsigned int type;
 	struct work_struct work;
 };
 
@@ -938,7 +925,7 @@  static inline struct wm_coeff_ctl *bytes_ext_to_ctl(struct soc_bytes_ext *ext)
 	return container_of(ext, struct wm_coeff_ctl, bytes_ext);
 }
 
-static int cs_dsp_coeff_base_reg(struct wm_coeff_ctl *ctl, unsigned int *reg)
+static int cs_dsp_coeff_base_reg(struct cs_dsp_coeff_ctl *ctl, unsigned int *reg)
 {
 	const struct cs_dsp_alg_region *alg_region = &ctl->alg_region;
 	struct wm_adsp *dsp = ctl->dsp;
@@ -962,8 +949,9 @@  static int wm_coeff_info(struct snd_kcontrol *kctl,
 	struct soc_bytes_ext *bytes_ext =
 		(struct soc_bytes_ext *)kctl->private_value;
 	struct wm_coeff_ctl *ctl = bytes_ext_to_ctl(bytes_ext);
+	struct cs_dsp_coeff_ctl *cs_ctl = ctl->cs_ctl;
 
-	switch (ctl->type) {
+	switch (cs_ctl->type) {
 	case WMFW_CTL_TYPE_ACKED:
 		uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
 		uinfo->value.integer.min = CS_DSP_ACKED_CTL_MIN_VALUE;
@@ -973,14 +961,14 @@  static int wm_coeff_info(struct snd_kcontrol *kctl,
 		break;
 	default:
 		uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES;
-		uinfo->count = ctl->len;
+		uinfo->count = cs_ctl->len;
 		break;
 	}
 
 	return 0;
 }
 
-static int cs_dsp_coeff_write_acked_control(struct wm_coeff_ctl *ctl,
+static int cs_dsp_coeff_write_acked_control(struct cs_dsp_coeff_ctl *ctl,
 					    unsigned int event_id)
 {
 	struct wm_adsp *dsp = ctl->dsp;
@@ -1040,7 +1028,7 @@  static int cs_dsp_coeff_write_acked_control(struct wm_coeff_ctl *ctl,
 	return -ETIMEDOUT;
 }
 
-static int cs_dsp_coeff_write_ctrl_raw(struct wm_coeff_ctl *ctl,
+static int cs_dsp_coeff_write_ctrl_raw(struct cs_dsp_coeff_ctl *ctl,
 				       const void *buf, size_t len)
 {
 	struct wm_adsp *dsp = ctl->dsp;
@@ -1071,7 +1059,7 @@  static int cs_dsp_coeff_write_ctrl_raw(struct wm_coeff_ctl *ctl,
 	return 0;
 }
 
-static int cs_dsp_coeff_write_ctrl(struct wm_coeff_ctl *ctl,
+static int cs_dsp_coeff_write_ctrl(struct cs_dsp_coeff_ctl *ctl,
 				   const void *buf, size_t len)
 {
 	int ret = 0;
@@ -1094,12 +1082,13 @@  static int wm_coeff_put(struct snd_kcontrol *kctl,
 	struct soc_bytes_ext *bytes_ext =
 		(struct soc_bytes_ext *)kctl->private_value;
 	struct wm_coeff_ctl *ctl = bytes_ext_to_ctl(bytes_ext);
+	struct cs_dsp_coeff_ctl *cs_ctl = ctl->cs_ctl;
 	char *p = ucontrol->value.bytes.data;
 	int ret = 0;
 
-	mutex_lock(&ctl->dsp->pwr_lock);
-	ret = cs_dsp_coeff_write_ctrl(ctl, p, ctl->len);
-	mutex_unlock(&ctl->dsp->pwr_lock);
+	mutex_lock(&cs_ctl->dsp->pwr_lock);
+	ret = cs_dsp_coeff_write_ctrl(cs_ctl, p, cs_ctl->len);
+	mutex_unlock(&cs_ctl->dsp->pwr_lock);
 
 	return ret;
 }
@@ -1110,16 +1099,17 @@  static int wm_coeff_tlv_put(struct snd_kcontrol *kctl,
 	struct soc_bytes_ext *bytes_ext =
 		(struct soc_bytes_ext *)kctl->private_value;
 	struct wm_coeff_ctl *ctl = bytes_ext_to_ctl(bytes_ext);
+	struct cs_dsp_coeff_ctl *cs_ctl = ctl->cs_ctl;
 	int ret = 0;
 
-	mutex_lock(&ctl->dsp->pwr_lock);
+	mutex_lock(&cs_ctl->dsp->pwr_lock);
 
-	if (copy_from_user(ctl->cache, bytes, size))
+	if (copy_from_user(cs_ctl->cache, bytes, size))
 		ret = -EFAULT;
 	else
-		ret = cs_dsp_coeff_write_ctrl(ctl, ctl->cache, size);
+		ret = cs_dsp_coeff_write_ctrl(cs_ctl, cs_ctl->cache, size);
 
-	mutex_unlock(&ctl->dsp->pwr_lock);
+	mutex_unlock(&cs_ctl->dsp->pwr_lock);
 
 	return ret;
 }
@@ -1130,25 +1120,26 @@  static int wm_coeff_put_acked(struct snd_kcontrol *kctl,
 	struct soc_bytes_ext *bytes_ext =
 		(struct soc_bytes_ext *)kctl->private_value;
 	struct wm_coeff_ctl *ctl = bytes_ext_to_ctl(bytes_ext);
+	struct cs_dsp_coeff_ctl *cs_ctl = ctl->cs_ctl;
 	unsigned int val = ucontrol->value.integer.value[0];
 	int ret;
 
 	if (val == 0)
 		return 0;	/* 0 means no event */
 
-	mutex_lock(&ctl->dsp->pwr_lock);
+	mutex_lock(&cs_ctl->dsp->pwr_lock);
 
-	if (ctl->enabled && ctl->dsp->running)
-		ret = cs_dsp_coeff_write_acked_control(ctl, val);
+	if (cs_ctl->enabled && cs_ctl->dsp->running)
+		ret = cs_dsp_coeff_write_acked_control(cs_ctl, val);
 	else
 		ret = -EPERM;
 
-	mutex_unlock(&ctl->dsp->pwr_lock);
+	mutex_unlock(&cs_ctl->dsp->pwr_lock);
 
 	return ret;
 }
 
-static int cs_dsp_coeff_read_ctrl_raw(struct wm_coeff_ctl *ctl,
+static int cs_dsp_coeff_read_ctrl_raw(struct cs_dsp_coeff_ctl *ctl,
 				      void *buf, size_t len)
 {
 	struct wm_adsp *dsp = ctl->dsp;
@@ -1179,7 +1170,7 @@  static int cs_dsp_coeff_read_ctrl_raw(struct wm_coeff_ctl *ctl,
 	return 0;
 }
 
-static int cs_dsp_coeff_read_ctrl(struct wm_coeff_ctl *ctl, void *buf, size_t len)
+static int cs_dsp_coeff_read_ctrl(struct cs_dsp_coeff_ctl *ctl, void *buf, size_t len)
 {
 	int ret = 0;
 
@@ -1205,12 +1196,13 @@  static int wm_coeff_get(struct snd_kcontrol *kctl,
 	struct soc_bytes_ext *bytes_ext =
 		(struct soc_bytes_ext *)kctl->private_value;
 	struct wm_coeff_ctl *ctl = bytes_ext_to_ctl(bytes_ext);
+	struct cs_dsp_coeff_ctl *cs_ctl = ctl->cs_ctl;
 	char *p = ucontrol->value.bytes.data;
 	int ret;
 
-	mutex_lock(&ctl->dsp->pwr_lock);
-	ret = cs_dsp_coeff_read_ctrl(ctl, p, ctl->len);
-	mutex_unlock(&ctl->dsp->pwr_lock);
+	mutex_lock(&cs_ctl->dsp->pwr_lock);
+	ret = cs_dsp_coeff_read_ctrl(cs_ctl, p, cs_ctl->len);
+	mutex_unlock(&cs_ctl->dsp->pwr_lock);
 
 	return ret;
 }
@@ -1221,16 +1213,17 @@  static int wm_coeff_tlv_get(struct snd_kcontrol *kctl,
 	struct soc_bytes_ext *bytes_ext =
 		(struct soc_bytes_ext *)kctl->private_value;
 	struct wm_coeff_ctl *ctl = bytes_ext_to_ctl(bytes_ext);
+	struct cs_dsp_coeff_ctl *cs_ctl = ctl->cs_ctl;
 	int ret = 0;
 
-	mutex_lock(&ctl->dsp->pwr_lock);
+	mutex_lock(&cs_ctl->dsp->pwr_lock);
 
-	ret = cs_dsp_coeff_read_ctrl(ctl, ctl->cache, size);
+	ret = cs_dsp_coeff_read_ctrl(cs_ctl, cs_ctl->cache, size);
 
-	if (!ret && copy_to_user(bytes, ctl->cache, size))
+	if (!ret && copy_to_user(bytes, cs_ctl->cache, size))
 		ret = -EFAULT;
 
-	mutex_unlock(&ctl->dsp->pwr_lock);
+	mutex_unlock(&cs_ctl->dsp->pwr_lock);
 
 	return ret;
 }
@@ -1283,12 +1276,10 @@  static unsigned int wmfw_convert_flags(unsigned int in, unsigned int len)
 
 static int wmfw_add_ctl(struct wm_adsp *dsp, struct wm_coeff_ctl *ctl)
 {
+	struct cs_dsp_coeff_ctl *cs_ctl = ctl->cs_ctl;
 	struct snd_kcontrol_new *kcontrol;
 	int ret;
 
-	if (!ctl || !ctl->name)
-		return -EINVAL;
-
 	kcontrol = kzalloc(sizeof(*kcontrol), GFP_KERNEL);
 	if (!kcontrol)
 		return -ENOMEM;
@@ -1298,16 +1289,16 @@  static int wmfw_add_ctl(struct wm_adsp *dsp, struct wm_coeff_ctl *ctl)
 	kcontrol->iface = SNDRV_CTL_ELEM_IFACE_MIXER;
 	kcontrol->tlv.c = snd_soc_bytes_tlv_callback;
 	kcontrol->private_value = (unsigned long)&ctl->bytes_ext;
-	kcontrol->access = wmfw_convert_flags(ctl->flags, ctl->len);
+	kcontrol->access = wmfw_convert_flags(cs_ctl->flags, cs_ctl->len);
 
-	switch (ctl->type) {
+	switch (cs_ctl->type) {
 	case WMFW_CTL_TYPE_ACKED:
 		kcontrol->get = wm_coeff_get_acked;
 		kcontrol->put = wm_coeff_put_acked;
 		break;
 	default:
 		if (kcontrol->access & SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK) {
-			ctl->bytes_ext.max = ctl->len;
+			ctl->bytes_ext.max = cs_ctl->len;
 			ctl->bytes_ext.get = wm_coeff_tlv_get;
 			ctl->bytes_ext.put = wm_coeff_tlv_put;
 		} else {
@@ -1332,7 +1323,7 @@  static int wmfw_add_ctl(struct wm_adsp *dsp, struct wm_coeff_ctl *ctl)
 
 static int cs_dsp_coeff_init_control_caches(struct wm_adsp *dsp)
 {
-	struct wm_coeff_ctl *ctl;
+	struct cs_dsp_coeff_ctl *ctl;
 	int ret;
 
 	list_for_each_entry(ctl, &dsp->ctl_list, list) {
@@ -1358,7 +1349,7 @@  static int cs_dsp_coeff_init_control_caches(struct wm_adsp *dsp)
 
 static int cs_dsp_coeff_sync_controls(struct wm_adsp *dsp)
 {
-	struct wm_coeff_ctl *ctl;
+	struct cs_dsp_coeff_ctl *ctl;
 	int ret;
 
 	list_for_each_entry(ctl, &dsp->ctl_list, list) {
@@ -1378,7 +1369,7 @@  static int cs_dsp_coeff_sync_controls(struct wm_adsp *dsp)
 static void cs_dsp_signal_event_controls(struct wm_adsp *dsp,
 					  unsigned int event)
 {
-	struct wm_coeff_ctl *ctl;
+	struct cs_dsp_coeff_ctl *ctl;
 	int ret;
 
 	list_for_each_entry(ctl, &dsp->ctl_list, list) {
@@ -1401,47 +1392,30 @@  static void wm_adsp_ctl_work(struct work_struct *work)
 	struct wm_coeff_ctl *ctl = container_of(work,
 						struct wm_coeff_ctl,
 						work);
-
-	wmfw_add_ctl(ctl->dsp, ctl);
+	wmfw_add_ctl(ctl->cs_ctl->dsp, ctl);
 }
 
-static void cs_dsp_free_ctl_blk(struct wm_coeff_ctl *ctl)
+static void cs_dsp_free_ctl_blk(struct cs_dsp_coeff_ctl *ctl)
 {
-	cancel_work_sync(&ctl->work);
-
 	kfree(ctl->cache);
-	kfree(ctl->name);
 	kfree(ctl->subname);
 	kfree(ctl);
 }
 
-static int cs_dsp_create_control(struct wm_adsp *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)
+static int wm_adsp_control_add(struct cs_dsp_coeff_ctl *cs_ctl)
 {
+	struct wm_adsp *dsp = cs_ctl->dsp;
 	struct wm_coeff_ctl *ctl;
 	char name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
 	const char *region_name;
 	int ret;
 
-	list_for_each_entry(ctl, &dsp->ctl_list, list) {
-		if (ctl->fw_name == wm_adsp_fw_text[dsp->fw] &&
-		    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;
-			}
-		}
-	}
+	if (cs_ctl->flags & WMFW_CTL_FLAG_SYS)
+		return 0;
 
-	region_name = cs_dsp_mem_region_name(alg_region->type);
+	region_name = cs_dsp_mem_region_name(cs_ctl->alg_region.type);
 	if (!region_name) {
-		cs_dsp_err(dsp, "Unknown region type: %d\n", alg_region->type);
+		adsp_err(dsp, "Unknown region type: %d\n", cs_ctl->alg_region.type);
 		return -EINVAL;
 	}
 
@@ -1449,22 +1423,21 @@  static int cs_dsp_create_control(struct wm_adsp *dsp,
 	case 0:
 	case 1:
 		snprintf(name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN, "%s %s %x",
-			 dsp->name, region_name, alg_region->alg);
-		subname = NULL; /* don't append subname */
+			 dsp->name, region_name, cs_ctl->alg_region.alg);
 		break;
 	case 2:
 		ret = scnprintf(name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN,
 				"%s%c %.12s %x", dsp->name, *region_name,
-				wm_adsp_fw_text[dsp->fw], alg_region->alg);
+				wm_adsp_fw_text[dsp->fw], cs_ctl->alg_region.alg);
 		break;
 	default:
 		ret = scnprintf(name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN,
 				"%s %.12s %x", dsp->name,
-				wm_adsp_fw_text[dsp->fw], alg_region->alg);
+				wm_adsp_fw_text[dsp->fw], cs_ctl->alg_region.alg);
 		break;
 	}
 
-	if (subname) {
+	if (cs_ctl->subname) {
 		int avail = SNDRV_CTL_ELEM_ID_NAME_MAXLEN - ret - 2;
 		int skip = 0;
 
@@ -1472,30 +1445,81 @@  static int cs_dsp_create_control(struct wm_adsp *dsp,
 			avail -= strlen(dsp->component->name_prefix) + 1;
 
 		/* Truncate the subname from the start if it is too long */
-		if (subname_len > avail)
-			skip = subname_len - avail;
+		if (cs_ctl->subname_len > avail)
+			skip = cs_ctl->subname_len - avail;
 
 		snprintf(name + ret, SNDRV_CTL_ELEM_ID_NAME_MAXLEN - ret,
-			 " %.*s", subname_len - skip, subname + skip);
+			 " %.*s", cs_ctl->subname_len - skip, cs_ctl->subname + skip);
 	}
 
 	ctl = kzalloc(sizeof(*ctl), GFP_KERNEL);
 	if (!ctl)
 		return -ENOMEM;
-	ctl->fw_name = wm_adsp_fw_text[dsp->fw];
-	ctl->alg_region = *alg_region;
+	ctl->cs_ctl = cs_ctl;
+
 	ctl->name = kmemdup(name, strlen(name) + 1, GFP_KERNEL);
 	if (!ctl->name) {
 		ret = -ENOMEM;
 		goto err_ctl;
 	}
-	if (subname) {
+
+	cs_ctl->priv = ctl;
+
+	INIT_WORK(&ctl->work, wm_adsp_ctl_work);
+	schedule_work(&ctl->work);
+
+	return 0;
+
+err_ctl:
+	kfree(ctl);
+
+	return ret;
+}
+
+static void wm_adsp_control_remove(struct cs_dsp_coeff_ctl *cs_ctl)
+{
+	struct wm_coeff_ctl *ctl = cs_ctl->priv;
+
+	cancel_work_sync(&ctl->work);
+
+	kfree(ctl->name);
+	kfree(ctl);
+}
+
+static int cs_dsp_create_control(struct wm_adsp *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 == wm_adsp_fw_text[dsp->fw] &&
+		    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 = wm_adsp_fw_text[dsp->fw];
+	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_name;
+			goto err_ctl;
 		}
 	}
 	ctl->enabled = 1;
@@ -1514,18 +1538,17 @@  static int cs_dsp_create_control(struct wm_adsp *dsp,
 
 	list_add(&ctl->list, &dsp->ctl_list);
 
-	if (flags & WMFW_CTL_FLAG_SYS)
-		return 0;
-
-	INIT_WORK(&ctl->work, wm_adsp_ctl_work);
-	schedule_work(&ctl->work);
+	ret = wm_adsp_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_name:
-	kfree(ctl->name);
 err_ctl:
 	kfree(ctl);
 
@@ -2013,14 +2036,14 @@  static int cs_dsp_load(struct wm_adsp *dsp)
 }
 
 /*
- * Find wm_coeff_ctl with input name as its subname
+ * Find cs_dsp_coeff_ctl with input name as its subname
  * If not found, return NULL
  */
-static struct wm_coeff_ctl *cs_dsp_get_ctl(struct wm_adsp *dsp,
-					   const char *name, int type,
-					   unsigned int alg)
+static struct cs_dsp_coeff_ctl *cs_dsp_get_ctl(struct wm_adsp *dsp,
+					       const char *name, int type,
+					       unsigned int alg)
 {
-	struct wm_coeff_ctl *pos, *rslt = NULL;
+	struct cs_dsp_coeff_ctl *pos, *rslt = NULL;
 	const char *fw_txt = wm_adsp_fw_text[dsp->fw];
 
 	list_for_each_entry(pos, &dsp->ctl_list, list) {
@@ -2041,23 +2064,26 @@  static struct wm_coeff_ctl *cs_dsp_get_ctl(struct wm_adsp *dsp,
 int wm_adsp_write_ctl(struct wm_adsp *dsp, const char *name, int type,
 		      unsigned int alg, void *buf, size_t len)
 {
+	struct cs_dsp_coeff_ctl *cs_ctl;
 	struct wm_coeff_ctl *ctl;
 	struct snd_kcontrol *kcontrol;
 	char ctl_name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
 	int ret;
 
-	ctl = cs_dsp_get_ctl(dsp, name, type, alg);
-	if (!ctl)
+	cs_ctl = cs_dsp_get_ctl(dsp, name, type, alg);
+	if (!cs_ctl)
 		return -EINVAL;
 
-	if (len > ctl->len)
+	ctl = cs_ctl->priv;
+
+	if (len > cs_ctl->len)
 		return -EINVAL;
 
-	ret = cs_dsp_coeff_write_ctrl(ctl, buf, len);
+	ret = cs_dsp_coeff_write_ctrl(cs_ctl, buf, len);
 	if (ret)
 		return ret;
 
-	if (ctl->flags & WMFW_CTL_FLAG_SYS)
+	if (cs_ctl->flags & WMFW_CTL_FLAG_SYS)
 		return 0;
 
 	if (dsp->component->name_prefix)
@@ -2083,23 +2109,23 @@  EXPORT_SYMBOL_GPL(wm_adsp_write_ctl);
 int wm_adsp_read_ctl(struct wm_adsp *dsp, const char *name, int type,
 		     unsigned int alg, void *buf, size_t len)
 {
-	struct wm_coeff_ctl *ctl;
+	struct cs_dsp_coeff_ctl *cs_ctl;
 
-	ctl = cs_dsp_get_ctl(dsp, name, type, alg);
-	if (!ctl)
+	cs_ctl = cs_dsp_get_ctl(dsp, name, type, alg);
+	if (!cs_ctl)
 		return -EINVAL;
 
-	if (len > ctl->len)
+	if (len > cs_ctl->len)
 		return -EINVAL;
 
-	return cs_dsp_coeff_read_ctrl(ctl, buf, len);
+	return cs_dsp_coeff_read_ctrl(cs_ctl, buf, len);
 }
 EXPORT_SYMBOL_GPL(wm_adsp_read_ctl);
 
 static void cs_dsp_ctl_fixup_base(struct wm_adsp *dsp,
 				  const struct cs_dsp_alg_region *alg_region)
 {
-	struct wm_coeff_ctl *ctl;
+	struct cs_dsp_coeff_ctl *ctl;
 
 	list_for_each_entry(ctl, &dsp->ctl_list, list) {
 		if (ctl->fw_name == wm_adsp_fw_text[dsp->fw] &&
@@ -2885,7 +2911,7 @@  static int cs_dsp_adsp1_power_up(struct wm_adsp *dsp)
 
 static void cs_dsp_adsp1_power_down(struct wm_adsp *dsp)
 {
-	struct wm_coeff_ctl *ctl;
+	struct cs_dsp_coeff_ctl *ctl;
 
 	mutex_lock(&dsp->pwr_lock);
 
@@ -3199,7 +3225,7 @@  static void cs_dsp_power_up(struct wm_adsp *dsp)
 
 static void cs_dsp_power_down(struct wm_adsp *dsp)
 {
-	struct wm_coeff_ctl *ctl;
+	struct cs_dsp_coeff_ctl *ctl;
 
 	mutex_lock(&dsp->pwr_lock);
 
@@ -3496,11 +3522,13 @@  EXPORT_SYMBOL_GPL(wm_halo_init);
 
 static void cs_dsp_remove(struct wm_adsp *dsp)
 {
-	struct wm_coeff_ctl *ctl;
+	struct cs_dsp_coeff_ctl *ctl;
 
 	while (!list_empty(&dsp->ctl_list)) {
-		ctl = list_first_entry(&dsp->ctl_list, struct wm_coeff_ctl,
-					list);
+		ctl = list_first_entry(&dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
+
+		wm_adsp_control_remove(ctl);
+
 		list_del(&ctl->list);
 		cs_dsp_free_ctl_blk(ctl);
 	}
@@ -3936,15 +3964,16 @@  static int wm_adsp_buffer_parse_legacy(struct wm_adsp *dsp)
 	return 0;
 }
 
-static int wm_adsp_buffer_parse_coeff(struct wm_coeff_ctl *ctl)
+static int wm_adsp_buffer_parse_coeff(struct cs_dsp_coeff_ctl *cs_ctl)
 {
 	struct wm_adsp_host_buf_coeff_v1 coeff_v1;
 	struct wm_adsp_compr_buf *buf;
+	struct wm_adsp *dsp = cs_ctl->dsp;
 	unsigned int version;
 	int ret, i;
 
 	for (i = 0; i < 5; ++i) {
-		ret = cs_dsp_coeff_read_ctrl(ctl, &coeff_v1, sizeof(coeff_v1));
+		ret = cs_dsp_coeff_read_ctrl(cs_ctl, &coeff_v1, sizeof(coeff_v1));
 		if (ret < 0)
 			return ret;
 
@@ -3955,15 +3984,15 @@  static int wm_adsp_buffer_parse_coeff(struct wm_coeff_ctl *ctl)
 	}
 
 	if (!coeff_v1.host_buf_ptr) {
-		adsp_err(ctl->dsp, "Failed to acquire host buffer\n");
+		adsp_err(dsp, "Failed to acquire host buffer\n");
 		return -EIO;
 	}
 
-	buf = wm_adsp_buffer_alloc(ctl->dsp);
+	buf = wm_adsp_buffer_alloc(dsp);
 	if (!buf)
 		return -ENOMEM;
 
-	buf->host_buf_mem_type = ctl->alg_region.type;
+	buf->host_buf_mem_type = cs_ctl->alg_region.type;
 	buf->host_buf_ptr = be32_to_cpu(coeff_v1.host_buf_ptr);
 
 	ret = wm_adsp_buffer_populate(buf);
@@ -3974,7 +4003,7 @@  static int wm_adsp_buffer_parse_coeff(struct wm_coeff_ctl *ctl)
 	 * v0 host_buffer coefficients didn't have versioning, so if the
 	 * control is one word, assume version 0.
 	 */
-	if (ctl->len == 4) {
+	if (cs_ctl->len == 4) {
 		compr_dbg(buf, "host_buf_ptr=%x\n", buf->host_buf_ptr);
 		return 0;
 	}
@@ -3983,7 +4012,7 @@  static int wm_adsp_buffer_parse_coeff(struct wm_coeff_ctl *ctl)
 	version >>= HOST_BUF_COEFF_COMPAT_VER_SHIFT;
 
 	if (version > HOST_BUF_COEFF_SUPPORTED_COMPAT_VER) {
-		adsp_err(ctl->dsp,
+		adsp_err(dsp,
 			 "Host buffer coeff ver %u > supported version %u\n",
 			 version, HOST_BUF_COEFF_SUPPORTED_COMPAT_VER);
 		return -EINVAL;
@@ -3991,7 +4020,7 @@  static int wm_adsp_buffer_parse_coeff(struct wm_coeff_ctl *ctl)
 
 	cs_dsp_remove_padding((u32 *)&coeff_v1.name, ARRAY_SIZE(coeff_v1.name));
 
-	buf->name = kasprintf(GFP_KERNEL, "%s-dsp-%s", ctl->dsp->part,
+	buf->name = kasprintf(GFP_KERNEL, "%s-dsp-%s", dsp->part,
 			      (char *)&coeff_v1.name);
 
 	compr_dbg(buf, "host_buf_ptr=%x coeff version %u\n",
@@ -4002,17 +4031,17 @@  static int wm_adsp_buffer_parse_coeff(struct wm_coeff_ctl *ctl)
 
 static int wm_adsp_buffer_init(struct wm_adsp *dsp)
 {
-	struct wm_coeff_ctl *ctl;
+	struct cs_dsp_coeff_ctl *cs_ctl;
 	int ret;
 
-	list_for_each_entry(ctl, &dsp->ctl_list, list) {
-		if (ctl->type != WMFW_CTL_TYPE_HOST_BUFFER)
+	list_for_each_entry(cs_ctl, &dsp->ctl_list, list) {
+		if (cs_ctl->type != WMFW_CTL_TYPE_HOST_BUFFER)
 			continue;
 
-		if (!ctl->enabled)
+		if (!cs_ctl->enabled)
 			continue;
 
-		ret = wm_adsp_buffer_parse_coeff(ctl);
+		ret = wm_adsp_buffer_parse_coeff(cs_ctl);
 		if (ret < 0) {
 			adsp_err(dsp, "Failed to parse coeff: %d\n", ret);
 			goto error;
diff --git a/sound/soc/codecs/wm_adsp.h b/sound/soc/codecs/wm_adsp.h
index 98b12b485916..eee298e94946 100644
--- a/sound/soc/codecs/wm_adsp.h
+++ b/sound/soc/codecs/wm_adsp.h
@@ -49,10 +49,30 @@  struct cs_dsp_alg_region {
 	unsigned int base;
 };
 
+struct wm_adsp;
 struct wm_adsp_compr;
 struct wm_adsp_compr_buf;
 struct cs_dsp_ops;
 
+struct cs_dsp_coeff_ctl {
+	const char *fw_name;
+	/* Subname is needed to match with firmware */
+	const char *subname;
+	unsigned int subname_len;
+	struct cs_dsp_alg_region alg_region;
+	struct wm_adsp *dsp;
+	unsigned int enabled:1;
+	struct list_head list;
+	void *cache;
+	unsigned int offset;
+	size_t len;
+	unsigned int set:1;
+	unsigned int flags;
+	unsigned int type;
+
+	void *priv;
+};
+
 struct wm_adsp {
 	const char *part;
 	const char *name;