From 796fad441cb248c1eac88bfb3a5929bb1a10fabb Mon Sep 17 00:00:00 2001
From: Vaibhav Agarwal <vaibhav.agarwal@linaro.org>
Date: Thu, 28 Jan 2016 21:15:39 +0530
Subject: [PATCH] greybus: audio: codec driver cleanup

audio codec driver is now moved to bundle driver approach.
This resolved many race conditions related to audio mgmt &
data connection init/exit sequence.
Thus, a lot of helper functions can now be safely removed.

Signed-off-by: Vaibhav Agarwal <vaibhav.agarwal@linaro.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
---
 drivers/staging/greybus/audio_codec.c    | 622 ++++++++---------------
 drivers/staging/greybus/audio_codec.h    |  21 +-
 drivers/staging/greybus/audio_topology.c |  99 +---
 3 files changed, 230 insertions(+), 512 deletions(-)

diff --git a/drivers/staging/greybus/audio_codec.c b/drivers/staging/greybus/audio_codec.c
index b43b5432d7a64..ad28c10fa154c 100644
--- a/drivers/staging/greybus/audio_codec.c
+++ b/drivers/staging/greybus/audio_codec.c
@@ -18,30 +18,38 @@
 static DEFINE_MUTEX(gb_codec_list_lock);
 static LIST_HEAD(gb_codec_list);
 
+struct gbaudio_dai *gbaudio_find_dai(struct gbaudio_codec_info *gbcodec,
+				     int data_cport, const char *name)
+{
+	struct gbaudio_dai *dai;
+
+	list_for_each_entry(dai, &gbcodec->dai_list, list) {
+		if (name && !strncmp(dai->name, name, NAME_SIZE))
+			return dai;
+		if ((data_cport != -1) && (dai->data_cport == data_cport))
+			return dai;
+	}
+	return NULL;
+}
+
 /*
  * codec DAI ops
  */
 static int gbcodec_startup(struct snd_pcm_substream *substream,
 			   struct snd_soc_dai *dai)
 {
-	int ret, found;
+	int ret;
 	__u16 i2s_port, cportid;
 
 	struct gbaudio_dai *gb_dai;
-	struct gb_audio *audio = dev_get_drvdata(dai->dev);
-	struct gbaudio_codec_info *gb = audio->gbcodec;
+	struct gbaudio_codec_info *gb = dev_get_drvdata(dai->dev);
 
 	/* find the dai */
-	found = 0;
-	list_for_each_entry(gb_dai, &gb->dai_list, list) {
-		if (!strncmp(gb_dai->name, dai->name, NAME_SIZE)) {
-			found = 1;
-			break;
-		}
-	}
-
-	if (!found) {
+	mutex_lock(&gb->lock);
+	gb_dai = gbaudio_find_dai(gb, -1, dai->name);
+	if (!gb_dai) {
 		dev_err(dai->dev, "%s: DAI not registered\n", dai->name);
+		mutex_unlock(&gb->lock);
 		return -EINVAL;
 	}
 
@@ -54,7 +62,8 @@ static int gbcodec_startup(struct snd_pcm_substream *substream,
 		ret);
 
 	if (!ret)
-		atomic_inc(&gb->users);
+		atomic_inc(&gb_dai->users);
+	mutex_unlock(&gb->lock);
 
 	return ret;
 }
@@ -62,28 +71,21 @@ static int gbcodec_startup(struct snd_pcm_substream *substream,
 static void gbcodec_shutdown(struct snd_pcm_substream *substream,
 			     struct snd_soc_dai *dai)
 {
-	int ret, found;
+	int ret;
 	__u16 i2s_port, cportid;
 
 	struct gbaudio_dai *gb_dai;
-	struct gb_audio *audio = dev_get_drvdata(dai->dev);
-	struct gbaudio_codec_info *gb = audio->gbcodec;
+	struct gbaudio_codec_info *gb = dev_get_drvdata(dai->dev);
 
 	/* find the dai */
-	found = 0;
-	list_for_each_entry(gb_dai, &gb->dai_list, list) {
-		if (!strncmp(gb_dai->name, dai->name, NAME_SIZE)) {
-			found = 1;
-			break;
-		}
-	}
-
-	if (!found) {
+	mutex_lock(&gb->lock);
+	gb_dai = gbaudio_find_dai(gb, -1, dai->name);
+	if (!gb_dai) {
 		dev_err(dai->dev, "%s: DAI not registered\n", dai->name);
-		return;
+		goto func_exit;
 	}
 
-	atomic_dec(&gb->users);
+	atomic_dec(&gb_dai->users);
 
 	/* deactivate rx/tx */
 	cportid = gb_dai->connection->intf_cport_id;
@@ -97,7 +99,7 @@ static void gbcodec_shutdown(struct snd_pcm_substream *substream,
 		break;
 	default:
 		dev_err(dai->dev, "Invalid stream type during shutdown\n");
-		return;
+		goto func_exit;
 	}
 
 	if (ret)
@@ -110,6 +112,8 @@ static void gbcodec_shutdown(struct snd_pcm_substream *substream,
 
 	dev_dbg(dai->dev, "Unregister %s:%d DAI, ret:%d\n", dai->name,
 		gb_dai->connection->hd_cport_id, ret);
+func_exit:
+	mutex_unlock(&gb->lock);
 
 	return;
 }
@@ -118,26 +122,20 @@ static int gbcodec_hw_params(struct snd_pcm_substream *substream,
 			     struct snd_pcm_hw_params *hwparams,
 			     struct snd_soc_dai *dai)
 {
-	int ret, found;
+	int ret;
 	uint8_t sig_bits, channels;
 	uint32_t format, rate;
 	uint16_t data_cport;
 	struct gbaudio_dai *gb_dai;
-	struct gb_audio *audio = dev_get_drvdata(dai->dev);
-	struct gbaudio_codec_info *gb = audio->gbcodec;
+	struct gbaudio_codec_info *gb = dev_get_drvdata(dai->dev);
 
 	/* find the dai */
-	found = 0;
-	list_for_each_entry(gb_dai, &gb->dai_list, list) {
-		if (!strncmp(gb_dai->name, dai->name, NAME_SIZE)) {
-			found = 1;
-			break;
-		}
-	}
-
-	if (!found) {
+	mutex_lock(&gb->lock);
+	gb_dai = gbaudio_find_dai(gb, -1, dai->name);
+	if (!gb_dai) {
 		dev_err(dai->dev, "%s: DAI not registered\n", dai->name);
-		return -EINVAL;
+		ret = -EINVAL;
+		goto func_exit;
 	}
 
 	/*
@@ -147,21 +145,24 @@ static int gbcodec_hw_params(struct snd_pcm_substream *substream,
 	if (params_channels(hwparams) != 2) {
 		dev_err(dai->dev, "Invalid channel count:%d\n",
 			params_channels(hwparams));
-		return -EINVAL;
+		ret = -EINVAL;
+		goto func_exit;
 	}
 	channels = params_channels(hwparams);
 
 	if (params_rate(hwparams) != 48000) {
 		dev_err(dai->dev, "Invalid sampling rate:%d\n",
 			params_rate(hwparams));
-		return -EINVAL;
+		ret = -EINVAL;
+		goto func_exit;
 	}
 	rate = GB_AUDIO_PCM_RATE_48000;
 
 	if (params_format(hwparams) != SNDRV_PCM_FORMAT_S16_LE) {
 		dev_err(dai->dev, "Invalid format:%d\n",
 			params_format(hwparams));
-		return -EINVAL;
+		ret = -EINVAL;
+		goto func_exit;
 	}
 	format = GB_AUDIO_PCM_FMT_S16_LE;
 
@@ -176,7 +177,7 @@ static int gbcodec_hw_params(struct snd_pcm_substream *substream,
 				  rate, channels, sig_bits);
 	if (ret) {
 		dev_err(dai->dev, "%d: Error during set_pcm\n", ret);
-		return ret;
+		goto func_exit;
 	}
 
 	/*
@@ -190,31 +191,26 @@ static int gbcodec_hw_params(struct snd_pcm_substream *substream,
 					    6144000);
 	if (ret)
 		dev_err(dai->dev, "%d: Error during set_config\n", ret);
-
+func_exit:
+	mutex_unlock(&gb->lock);
 	return ret;
 }
 
 static int gbcodec_prepare(struct snd_pcm_substream *substream,
 			   struct snd_soc_dai *dai)
 {
-	int ret, found;
+	int ret;
 	uint16_t data_cport;
 	struct gbaudio_dai *gb_dai;
-	struct gb_audio *audio = dev_get_drvdata(dai->dev);
-	struct gbaudio_codec_info *gb = audio->gbcodec;
+	struct gbaudio_codec_info *gb = dev_get_drvdata(dai->dev);
 
 	/* find the dai */
-	found = 0;
-	list_for_each_entry(gb_dai, &gb->dai_list, list) {
-		if (!strncmp(gb_dai->name, dai->name, NAME_SIZE)) {
-			found = 1;
-			break;
-		}
-	}
-
-	if (!found) {
+	mutex_lock(&gb->lock);
+	gb_dai = gbaudio_find_dai(gb, -1, dai->name);
+	if (!gb_dai) {
 		dev_err(dai->dev, "%s: DAI not registered\n", dai->name);
-		return -EINVAL;
+		ret = -EINVAL;
+		goto func_exit;
 	}
 
 	/* deactivate rx/tx */
@@ -228,7 +224,7 @@ static int gbcodec_prepare(struct snd_pcm_substream *substream,
 			dev_err(dai->dev,
 				"%d:Error during set_rx_data_size, cport:%d\n",
 				ret, data_cport);
-			return ret;
+			goto func_exit;
 		}
 		ret = gb_audio_apbridgea_set_rx_data_size(gb_dai->connection, 0,
 							  192);
@@ -236,7 +232,7 @@ static int gbcodec_prepare(struct snd_pcm_substream *substream,
 			dev_err(dai->dev,
 				"%d:Error during apbridgea_set_rx_data_size\n",
 				ret);
-			return ret;
+			goto func_exit;
 		}
 		ret = gb_audio_gb_activate_rx(gb->mgmt_connection, data_cport);
 		break;
@@ -247,7 +243,7 @@ static int gbcodec_prepare(struct snd_pcm_substream *substream,
 			dev_err(dai->dev,
 				"%d:Error during module set_tx_data_size, cport:%d\n",
 				ret, data_cport);
-			return ret;
+			goto func_exit;
 		}
 		ret = gb_audio_apbridgea_set_tx_data_size(gb_dai->connection, 0,
 							  192);
@@ -255,43 +251,40 @@ static int gbcodec_prepare(struct snd_pcm_substream *substream,
 			dev_err(dai->dev,
 				"%d:Error during apbridgea set_tx_data_size, cport\n",
 				ret);
-			return ret;
+			goto func_exit;
 		}
 		ret = gb_audio_gb_activate_tx(gb->mgmt_connection, data_cport);
 		break;
 	default:
 		dev_err(dai->dev, "Invalid stream type %d during prepare\n",
 			substream->stream);
-		return -EINVAL;
+		ret = -EINVAL;
+		goto func_exit;
 	}
 
 	if (ret)
 		dev_err(dai->dev, "%d: Error during activate stream\n", ret);
 
+func_exit:
+	mutex_unlock(&gb->lock);
 	return ret;
 }
 
 static int gbcodec_trigger(struct snd_pcm_substream *substream, int cmd,
 		struct snd_soc_dai *dai)
 {
-	int ret, found;
+	int ret;
 	int tx, rx, start, stop;
 	struct gbaudio_dai *gb_dai;
-	struct gb_audio *audio = dev_get_drvdata(dai->dev);
-	struct gbaudio_codec_info *gb = audio->gbcodec;
+	struct gbaudio_codec_info *gb = dev_get_drvdata(dai->dev);
 
 	/* find the dai */
-	found = 0;
-	list_for_each_entry(gb_dai, &gb->dai_list, list) {
-		if (!strncmp(gb_dai->name, dai->name, NAME_SIZE)) {
-			found = 1;
-			break;
-		}
-	}
-
-	if (!found) {
+	mutex_lock(&gb->lock);
+	gb_dai = gbaudio_find_dai(gb, -1, dai->name);
+	if (!gb_dai) {
 		dev_err(dai->dev, "%s: DAI not registered\n", dai->name);
-		return -EINVAL;
+		ret = -EINVAL;
+		goto func_exit;
 	}
 
 	tx = rx = start = stop = 0;
@@ -306,7 +299,8 @@ static int gbcodec_trigger(struct snd_pcm_substream *substream, int cmd,
 		break;
 	default:
 		dev_err(dai->dev, "Invalid tigger cmd:%d\n", cmd);
-		return -EINVAL;
+		ret = -EINVAL;
+		goto func_exit;
 	}
 
 	switch (substream->stream) {
@@ -319,7 +313,8 @@ static int gbcodec_trigger(struct snd_pcm_substream *substream, int cmd,
 	default:
 		dev_err(dai->dev, "Invalid stream type:%d\n",
 			substream->stream);
-		return -EINVAL;
+		ret = -EINVAL;
+		goto func_exit;
 	}
 
 	if (start && tx)
@@ -341,6 +336,8 @@ static int gbcodec_trigger(struct snd_pcm_substream *substream, int cmd,
 		dev_err(dai->dev, "%d:Error during %s stream\n", ret,
 			start ? "Start" : "Stop");
 
+func_exit:
+	mutex_unlock(&gb->lock);
 	return ret;
 }
 
@@ -383,8 +380,7 @@ static int gbcodec_write(struct snd_soc_codec *codec, unsigned int reg,
 			 unsigned int value)
 {
 	int ret = 0;
-	struct gb_audio *audio = snd_soc_codec_get_drvdata(codec);
-	struct gbaudio_codec_info *gbcodec = audio->gbcodec;
+	struct gbaudio_codec_info *gbcodec = snd_soc_codec_get_drvdata(codec);
 	u8 *gbcodec_reg = gbcodec->reg;
 
 	if (reg == SND_SOC_NOPM)
@@ -404,8 +400,7 @@ static unsigned int gbcodec_read(struct snd_soc_codec *codec,
 {
 	unsigned int val = 0;
 
-	struct gb_audio *audio = snd_soc_codec_get_drvdata(codec);
-	struct gbaudio_codec_info *gbcodec = audio->gbcodec;
+	struct gbaudio_codec_info *gbcodec = snd_soc_codec_get_drvdata(codec);
 	u8 *gbcodec_reg = gbcodec->reg;
 
 	if (reg == SND_SOC_NOPM)
@@ -447,28 +442,15 @@ static struct snd_soc_dai_link gbaudio_dailink = {
 	.be_id = 34,
 };
 
-static void gbaudio_remove_dailinks(struct gbaudio_codec_info *gbcodec)
-{
-	int i;
-
-	for (i = 0; i < gbcodec->num_dai_links; i++) {
-		dev_dbg(gbcodec->dev, "Remove %s: DAI link\n",
-			gbcodec->dailink_name[i]);
-		devm_kfree(gbcodec->dev, gbcodec->dailink_name[i]);
-		gbcodec->dailink_name[i] = NULL;
-	}
-	gbcodec->num_dai_links = 0;
-}
-
 static int gbaudio_add_dailinks(struct gbaudio_codec_info *gbcodec)
 {
 	int ret, i;
 	char *dai_link_name;
-	struct snd_soc_dai_link *dai;
+	struct snd_soc_dai_link *dailink;
 	struct device *dev = gbcodec->dev;
 
-	dai = &gbaudio_dailink;
-	dai->codec_name = gbcodec->name;
+	dailink = &gbaudio_dailink;
+	dailink->codec_name = gbcodec->name;
 
 	/* FIXME
 	 * allocate memory for DAI links based on count.
@@ -481,98 +463,20 @@ static int gbaudio_add_dailinks(struct gbaudio_codec_info *gbcodec)
 			devm_kzalloc(dev, NAME_SIZE, GFP_KERNEL);
 		snprintf(dai_link_name, NAME_SIZE, "GB %d.%d PRI_MI2S_RX",
 			 gbcodec->dev_id, i);
-		dai->name = dai_link_name;
-		dai->codec_dai_name = gbcodec->dais[i].name;
+		dailink->name = dai_link_name;
+		dailink->codec_dai_name = gbcodec->dais[i].name;
 	}
 
-	ret = msm8994_add_dailink("msm8994-tomtom-mtp-snd-card", dai, 1);
-	if (ret) {
+	ret = msm8994_add_dailink("msm8994-tomtom-mtp-snd-card", dailink, 1);
+	if (ret)
 		dev_err(dev, "%d:Error while adding DAI link\n", ret);
-		goto err_dai_link;
-	}
 
 	return ret;
-
-err_dai_link:
-	gbcodec->num_dai_links = i;
-	gbaudio_remove_dailinks(gbcodec);
-	return ret;
 }
 
 /*
  * gb_snd management functions
  */
-static struct gbaudio_codec_info *gbaudio_find_codec(struct device *dev,
-						     int dev_id)
-{
-	struct gbaudio_codec_info *tmp, *ret;
-
-	mutex_lock(&gb_codec_list_lock);
-	list_for_each_entry_safe(ret, tmp, &gb_codec_list, list) {
-		dev_dbg(dev, "%d:device found\n", ret->dev_id);
-		if (ret->dev_id == dev_id) {
-			mutex_unlock(&gb_codec_list_lock);
-			return ret;
-		}
-	}
-	mutex_unlock(&gb_codec_list_lock);
-	return NULL;
-}
-
-static struct gbaudio_codec_info *gbaudio_get_codec(struct device *dev,
-						    int dev_id)
-{
-	struct gbaudio_codec_info *gbcodec;
-	struct gb_audio *audio = dev_get_drvdata(dev);
-
-	gbcodec = gbaudio_find_codec(dev, dev_id);
-	if (gbcodec)
-		return gbcodec;
-
-	gbcodec = devm_kzalloc(dev, sizeof(*gbcodec), GFP_KERNEL);
-	if (!gbcodec)
-		return NULL;
-
-	mutex_init(&gbcodec->lock);
-	INIT_LIST_HEAD(&gbcodec->dai_list);
-	INIT_LIST_HEAD(&gbcodec->widget_list);
-	INIT_LIST_HEAD(&gbcodec->codec_ctl_list);
-	INIT_LIST_HEAD(&gbcodec->widget_ctl_list);
-	gbcodec->dev_id = dev_id;
-	audio->gbcodec = gbcodec;
-	gbcodec->dev = dev;
-	snprintf(gbcodec->name, NAME_SIZE, "%s.%s", dev->driver->name,
-		 dev_name(dev));
-
-	mutex_lock(&gb_codec_list_lock);
-	list_add(&gbcodec->list, &gb_codec_list);
-	mutex_unlock(&gb_codec_list_lock);
-	dev_dbg(dev, "%d:%s Added to codec list\n", gbcodec->dev_id,
-		gbcodec->name);
-
-	return gbcodec;
-}
-
-static void gbaudio_free_codec(struct device *dev,
-			       struct gbaudio_codec_info *gbcodec)
-{
-	struct gb_audio *audio = dev_get_drvdata(dev);
-
-	mutex_lock(&gb_codec_list_lock);
-	if (!gbcodec->mgmt_connection &&
-			list_empty(&gbcodec->dai_list)) {
-		list_del(&gbcodec->list);
-		mutex_unlock(&gb_codec_list_lock);
-		audio->gbcodec = NULL;
-		devm_kfree(dev, gbcodec);
-	} else {
-		mutex_unlock(&gb_codec_list_lock);
-	}
-}
-
-/*
- * This is the basic hook get things initialized and registered w/ gb
- */
 
 /* XXX
  * since BE DAI path is not yet properly closed from above layer,
@@ -593,7 +497,7 @@ static void gb_audio_cleanup(struct gbaudio_codec_info *gb)
 		 * In case of BE dailink, need to deactivate APBridge
 		 * manually
 		 */
-		if (gbaudio_dailink.no_pcm && atomic_read(&gb->users)) {
+		if (atomic_read(&gb_dai->users)) {
 			connection = gb_dai->connection;
 			/* PB active */
 			ret = gb_audio_apbridgea_stop_tx(connection, 0);
@@ -613,38 +517,34 @@ static void gb_audio_cleanup(struct gbaudio_codec_info *gb)
 			if (ret)
 				dev_info(dev, "%d:Failed during unregister cport\n",
 					 ret);
-			atomic_dec(&gb->users);
+			atomic_dec(&gb_dai->users);
 		}
 	}
 }
 
-static int gbaudio_codec_probe(struct gb_connection *connection)
+static int gbaudio_register_codec(struct gbaudio_codec_info *gbcodec)
 {
 	int ret, i;
-	struct gbaudio_codec_info *gbcodec;
+	struct device *dev = gbcodec->dev;
+	struct gb_connection *connection = gbcodec->mgmt_connection;
+	/*
+	 * FIXME: malloc for topology happens via audio_gb driver
+	 * should be done within codec driver itself
+	 */
 	struct gb_audio_topology *topology;
-	struct gb_audio_manager_module_descriptor desc;
-	struct device *dev = &connection->bundle->dev;
-	int dev_id = connection->intf->interface_id;
-
-	dev_dbg(dev, "Add device:%d:%s\n", dev_id, dev_name(dev));
-	/* get gbcodec data */
-	gbcodec = gbaudio_get_codec(dev, dev_id);
-	if (!gbcodec)
-		return -ENOMEM;
-
-	gbcodec->mgmt_connection = connection;
 
 	ret = gb_connection_enable(connection);
-	if (ret)
-		goto base_error;
+	if (ret) {
+		dev_err(dev, "%d: Error while enabling mgmt connection\n", ret);
+		return ret;
+	}
 
+	gbcodec->dev_id = connection->intf->interface_id;
 	/* fetch topology data */
 	ret = gb_audio_gb_get_topology(connection, &topology);
 	if (ret) {
-		dev_err(gbcodec->dev,
-			"%d:Error while fetching topology\n", ret);
-		goto err_connection_disable;
+		dev_err(dev, "%d:Error while fetching topology\n", ret);
+		goto tplg_fetch_err;
 	}
 
 	/* process topology data */
@@ -652,7 +552,7 @@ static int gbaudio_codec_probe(struct gb_connection *connection)
 	if (ret) {
 		dev_err(dev, "%d:Error while parsing topology data\n",
 			  ret);
-		goto topology_error;
+		goto tplg_parse_err;
 	}
 	gbcodec->topology = topology;
 
@@ -673,100 +573,39 @@ static int gbaudio_codec_probe(struct gb_connection *connection)
 				     gbcodec->dais, 1);
 	if (ret) {
 		dev_err(dev, "%d:Failed to register codec\n", ret);
-		goto parse_error;
+		goto codec_reg_err;
 	}
 
 	/* update DAI links in response to this codec */
 	ret = gbaudio_add_dailinks(gbcodec);
 	if (ret) {
 		dev_err(dev, "%d: Failed to add DAI links\n", ret);
-		goto codec_reg_error;
+		goto add_dailink_err;
 	}
 
-	/* set registered flag */
-	mutex_lock(&gbcodec->lock);
-	gbcodec->codec_registered = 1;
-
-	/* codec cleanup related */
-	atomic_set(&gbcodec->users, 0);
-
-	/* inform above layer for uevent */
-	if (!gbcodec->set_uevent &&
-	    (gbcodec->dai_added == gbcodec->num_dais)) {
-		dev_dbg(dev, "Inform set_event:%d to above layer\n", 1);
-		/* prepare for the audio manager */
-		strlcpy(desc.name, gbcodec->name,
-			GB_AUDIO_MANAGER_MODULE_NAME_LEN); /* todo */
-		desc.slot = 1; /* todo */
-		desc.vid = 2; /* todo */
-		desc.pid = 3; /* todo */
-		desc.cport = gbcodec->dev_id;
-		desc.devices = 0x2; /* todo */
-		gbcodec->manager_id = gb_audio_manager_add(&desc);
-		gbcodec->set_uevent = 1;
-	}
-	mutex_unlock(&gbcodec->lock);
-
-	return ret;
+	return 0;
 
-codec_reg_error:
+add_dailink_err:
 	snd_soc_unregister_codec(dev);
-	dev->driver = NULL;
-parse_error:
+codec_reg_err:
 	gbaudio_tplg_release(gbcodec);
 	gbcodec->topology = NULL;
-topology_error:
+tplg_parse_err:
 	kfree(topology);
-err_connection_disable:
-	gb_connection_disable(connection);
-base_error:
-	gbcodec->mgmt_connection = NULL;
-	gbaudio_free_codec(dev, gbcodec);
+tplg_fetch_err:
+	gb_connection_disable(gbcodec->mgmt_connection);
 	return ret;
 }
 
-static void gbaudio_codec_remove(struct gb_connection *connection)
+static void gbaudio_unregister_codec(struct gbaudio_codec_info *gbcodec)
 {
-	struct gbaudio_codec_info *gbcodec;
-	struct device *dev = &connection->bundle->dev;
-	int dev_id = connection->intf->interface_id;
-
-	dev_dbg(dev, "Remove device:%d:%s\n", dev_id, dev_name(dev));
-
-	/* get gbcodec data */
-	gbcodec = gbaudio_find_codec(dev, dev_id);
-	if (!gbcodec)
-		return;
-
-	/* inform uevent to above layers */
-	mutex_lock(&gbcodec->lock);
-	if (gbcodec->set_uevent) {
-		/* notify the audio manager */
-		dev_dbg(dev, "Inform set_event:%d to above layer\n", 0);
-		gb_audio_manager_remove(gbcodec->manager_id);
-		gbcodec->set_uevent = 0;
-	}
-	mutex_unlock(&gbcodec->lock);
-
-	if (atomic_read(&gbcodec->users)) {
-		dev_err(dev, "Cleanup Error: BE stream not yet closed\n");
-		gb_audio_cleanup(gbcodec);
-	}
-
+	gb_audio_cleanup(gbcodec);
 	msm8994_remove_dailink("msm8994-tomtom-mtp-snd-card", &gbaudio_dailink,
 			       1);
-	gbaudio_remove_dailinks(gbcodec);
-
-	snd_soc_unregister_codec(dev);
-	dev->driver = NULL;
+	snd_soc_unregister_codec(gbcodec->dev);
 	gbaudio_tplg_release(gbcodec);
 	kfree(gbcodec->topology);
-	gb_connection_disable(connection);
-	gbcodec->mgmt_connection = NULL;
-	mutex_lock(&gbcodec->lock);
-	gbcodec->codec_registered = 0;
-	mutex_unlock(&gbcodec->lock);
-	gbaudio_free_codec(dev, gbcodec);
+	gb_connection_disable(gbcodec->mgmt_connection);
 }
 
 static int gbaudio_codec_request_handler(struct gb_operation *op)
@@ -781,93 +620,6 @@ static int gbaudio_codec_request_handler(struct gb_operation *op)
 	return 0;
 }
 
-static int gbaudio_dai_probe(struct gb_connection *connection)
-{
-	struct gbaudio_dai *dai;
-	struct device *dev = &connection->bundle->dev;
-	int dev_id = connection->intf->interface_id;
-	struct gbaudio_codec_info *gbcodec;
-	struct gb_audio_manager_module_descriptor desc;
-	int ret;
-
-	dev_dbg(dev, "Add DAI device:%d:%s\n", dev_id, dev_name(dev));
-
-	/* get gbcodec data */
-	gbcodec = gbaudio_get_codec(dev, dev_id);
-	if (!gbcodec)
-		return -ENOMEM;
-
-	ret = gb_connection_enable(connection);
-	if (ret)
-		goto err_free_codec;
-
-	/* add/update dai_list*/
-	dai = gbaudio_add_dai(gbcodec, connection->intf_cport_id, connection,
-			       NULL);
-	if (!dai) {
-		ret = -ENOMEM;
-		goto err_connection_disable;
-	}
-
-	/* update dai_added count */
-	mutex_lock(&gbcodec->lock);
-	gbcodec->dai_added++;
-
-	/* inform above layer for uevent */
-	if (!gbcodec->set_uevent && gbcodec->codec_registered &&
-	    (gbcodec->dai_added == gbcodec->num_dais)) {
-		/* prepare for the audio manager */
-		dev_dbg(dev, "Inform set_event:%d to above layer\n", 1);
-		strlcpy(desc.name, gbcodec->name,
-			GB_AUDIO_MANAGER_MODULE_NAME_LEN); /* todo */
-		desc.slot = 1; /* todo */
-		desc.vid = 2; /* todo */
-		desc.pid = 3; /* todo */
-		desc.cport = gbcodec->dev_id;
-		desc.devices = 0x2; /* todo */
-		gbcodec->manager_id = gb_audio_manager_add(&desc);
-		gbcodec->set_uevent = 1;
-	}
-	mutex_unlock(&gbcodec->lock);
-
-	return 0;
-
-err_connection_disable:
-	gb_connection_disable(connection);
-err_free_codec:
-	gbaudio_free_codec(dev, gbcodec);
-	return ret;
-}
-
-static void gbaudio_dai_remove(struct gb_connection *connection)
-{
-	struct device *dev = &connection->bundle->dev;
-	int dev_id = connection->intf->interface_id;
-	struct gbaudio_codec_info *gbcodec;
-
-	dev_dbg(dev, "Remove DAI device:%d:%s\n", dev_id, dev_name(dev));
-
-	/* get gbcodec data */
-	gbcodec = gbaudio_find_codec(dev, dev_id);
-	if (!gbcodec)
-		return;
-
-	/* inform uevent to above layers */
-	mutex_lock(&gbcodec->lock);
-	if (gbcodec->set_uevent) {
-		/* notify the audio manager */
-		dev_dbg(dev, "Inform set_event:%d to above layer\n", 0);
-		gb_audio_manager_remove(gbcodec->manager_id);
-		gbcodec->set_uevent = 0;
-	}
-	/* update dai_added count */
-	gbcodec->dai_added--;
-	mutex_unlock(&gbcodec->lock);
-
-	gb_connection_disable(connection);
-	gbaudio_free_codec(dev, gbcodec);
-}
-
 static int gbaudio_dai_request_handler(struct gb_operation *op)
 {
 	struct gb_connection *connection = op->connection;
@@ -877,14 +629,14 @@ static int gbaudio_dai_request_handler(struct gb_operation *op)
 	return 0;
 }
 
-static int gb_audio_add_mgmt_connection(struct gb_audio *audio,
+static int gb_audio_add_mgmt_connection(struct gbaudio_codec_info *gbcodec,
 				struct greybus_descriptor_cport *cport_desc,
 				struct gb_bundle *bundle)
 {
 	struct gb_connection *connection;
 
 	/* Management Cport */
-	if (audio->mgmt_connection) {
+	if (gbcodec->mgmt_connection) {
 		dev_err(&bundle->dev,
 			"Can't have multiple Management connections\n");
 		return -ENODEV;
@@ -895,74 +647,99 @@ static int gb_audio_add_mgmt_connection(struct gb_audio *audio,
 	if (IS_ERR(connection))
 		return PTR_ERR(connection);
 
-	connection->private = audio;
-	audio->mgmt_connection = connection;
+	connection->private = gbcodec;
+	gbcodec->mgmt_connection = connection;
 
 	return 0;
 }
 
-static int gb_audio_add_data_connection(struct gb_audio *audio,
+static int gb_audio_add_data_connection(struct gbaudio_codec_info *gbcodec,
 				struct greybus_descriptor_cport *cport_desc,
-				struct gb_bundle *bundle, int index)
+				struct gb_bundle *bundle)
 {
 	struct gb_connection *connection;
+	struct gbaudio_dai *dai;
+
+	dai = devm_kzalloc(gbcodec->dev, sizeof(*dai), GFP_KERNEL);
+	if (!dai) {
+		dev_err(gbcodec->dev, "DAI Malloc failure\n");
+		return -ENOMEM;
+	}
 
 	connection = gb_connection_create(bundle, le16_to_cpu(cport_desc->id),
 					  gbaudio_dai_request_handler);
-	if (IS_ERR(connection))
+	if (IS_ERR(connection)) {
+		devm_kfree(gbcodec->dev, dai);
 		return PTR_ERR(connection);
+	}
 
-	connection->private = audio;
-	audio->data_connection[index] = connection;
+	connection->private = gbcodec;
+	atomic_set(&dai->users, 0);
+	dai->data_cport = connection->intf_cport_id;
+	dai->connection = connection;
+	list_add(&dai->list, &gbcodec->dai_list);
 
 	return 0;
 }
+/*
+ * This is the basic hook get things initialized and registered w/ gb
+ */
 
 static int gb_audio_probe(struct gb_bundle *bundle,
 			  const struct greybus_bundle_id *id)
 {
+	struct device *dev = &bundle->dev;
+	struct gbaudio_codec_info *gbcodec;
 	struct greybus_descriptor_cport *cport_desc;
-	struct gb_audio *audio;
+	struct gb_audio_manager_module_descriptor desc;
+	struct gbaudio_dai *dai, *_dai;
 	int ret, i;
-	int count = bundle->num_cports - 1;
 
 	/* There should be at least one Management and one Data cport */
 	if (bundle->num_cports < 2)
 		return -ENODEV;
 
+	mutex_lock(&gb_codec_list_lock);
 	/*
 	 * There can be only one Management connection and any number of data
 	 * connections.
 	 */
-	audio = kzalloc(sizeof(*audio) +
-			count * sizeof(*audio->data_connection), GFP_KERNEL);
-	if (!audio)
+	gbcodec = devm_kzalloc(dev, sizeof(*gbcodec), GFP_KERNEL);
+	if (!gbcodec) {
+		mutex_unlock(&gb_codec_list_lock);
 		return -ENOMEM;
+	}
 
-	audio->num_data_connections = count;
-	greybus_set_drvdata(bundle, audio);
+	gbcodec->num_data_connections = bundle->num_cports - 1;
+	mutex_init(&gbcodec->lock);
+	INIT_LIST_HEAD(&gbcodec->dai_list);
+	INIT_LIST_HEAD(&gbcodec->widget_list);
+	INIT_LIST_HEAD(&gbcodec->codec_ctl_list);
+	INIT_LIST_HEAD(&gbcodec->widget_ctl_list);
+	gbcodec->dev = dev;
+	snprintf(gbcodec->name, NAME_SIZE, "%s.%s", dev->driver->name,
+		 dev_name(dev));
+	greybus_set_drvdata(bundle, gbcodec);
 
 	/* Create all connections */
-	for (count = 0, i = 0; i < bundle->num_cports; i++) {
+	for (i = 0; i < bundle->num_cports; i++) {
 		cport_desc = &bundle->cport_desc[i];
 
 		switch (cport_desc->protocol_id) {
 		case GREYBUS_PROTOCOL_AUDIO_MGMT:
-			ret = gb_audio_add_mgmt_connection(audio, cport_desc,
+			ret = gb_audio_add_mgmt_connection(gbcodec, cport_desc,
 							   bundle);
 			if (ret)
 				goto destroy_connections;
 			break;
 		case GREYBUS_PROTOCOL_AUDIO_DATA:
-			ret = gb_audio_add_data_connection(audio, cport_desc,
-							   bundle, count);
+			ret = gb_audio_add_data_connection(gbcodec, cport_desc,
+							   bundle);
 			if (ret)
 				goto destroy_connections;
-
-			count++;
 			break;
 		default:
-			dev_err(&bundle->dev, "Unsupported protocol: 0x%02x\n",
+			dev_err(dev, "Unsupported protocol: 0x%02x\n",
 				cport_desc->protocol_id);
 			ret = -ENODEV;
 			goto destroy_connections;
@@ -970,57 +747,88 @@ static int gb_audio_probe(struct gb_bundle *bundle,
 	}
 
 	/* There must be a management cport */
-	if (!audio->mgmt_connection) {
+	if (!gbcodec->mgmt_connection) {
 		ret = -EINVAL;
-		dev_err(&bundle->dev, "Missing management connection\n");
+		dev_err(dev, "Missing management connection\n");
 		goto destroy_connections;
 	}
 
 	/* Initialize management connection */
-	ret = gbaudio_codec_probe(audio->mgmt_connection);
+	ret = gbaudio_register_codec(gbcodec);
 	if (ret)
 		goto destroy_connections;
 
 	/* Initialize data connections */
-	for (i = 0; i < audio->num_data_connections; i++) {
-		ret = gbaudio_dai_probe(audio->data_connection[i]);
+	list_for_each_entry(dai, &gbcodec->dai_list, list) {
+		ret = gb_connection_enable(dai->connection);
 		if (ret)
 			goto remove_dai;
 	}
 
+	/* inform above layer for uevent */
+	dev_dbg(dev, "Inform set_event:%d to above layer\n", 1);
+	/* prepare for the audio manager */
+	strlcpy(desc.name, gbcodec->name, GB_AUDIO_MANAGER_MODULE_NAME_LEN);
+	desc.slot = 1; /* todo */
+	desc.vid = 2; /* todo */
+	desc.pid = 3; /* todo */
+	desc.cport = gbcodec->dev_id;
+	desc.devices = 0x2; /* todo */
+	gbcodec->manager_id = gb_audio_manager_add(&desc);
+
+	list_add(&gbcodec->list, &gb_codec_list);
+	dev_dbg(dev, "Add GB Audio device:%s\n", gbcodec->name);
+	mutex_unlock(&gb_codec_list_lock);
+
 	return 0;
 
 remove_dai:
-	while (i--)
-		gbaudio_dai_remove(audio->data_connection[i]);
+	list_for_each_entry_safe(dai, _dai, &gbcodec->dai_list, list)
+		gb_connection_disable(dai->connection);
 
-	gbaudio_codec_remove(audio->mgmt_connection);
+	gbaudio_unregister_codec(gbcodec);
 destroy_connections:
-	while (count--)
-		gb_connection_destroy(audio->data_connection[count]);
+	list_for_each_entry_safe(dai, _dai, &gbcodec->dai_list, list) {
+		gb_connection_destroy(dai->connection);
+		list_del(&dai->list);
+		devm_kfree(dev, dai);
+	}
 
-	if (audio->mgmt_connection)
-		gb_connection_destroy(audio->mgmt_connection);
+	if (gbcodec->mgmt_connection)
+		gb_connection_destroy(gbcodec->mgmt_connection);
 
-	kfree(audio);
+	devm_kfree(dev, gbcodec);
+	mutex_unlock(&gb_codec_list_lock);
 
 	return ret;
 }
 
 static void gb_audio_disconnect(struct gb_bundle *bundle)
 {
-	struct gb_audio *audio = greybus_get_drvdata(bundle);
-	int i;
+	struct gbaudio_codec_info *gbcodec = greybus_get_drvdata(bundle);
+	struct gbaudio_dai *dai, *_dai;
 
-	for (i = audio->num_data_connections - 1; i >= 0; i--) {
-		gbaudio_dai_remove(audio->data_connection[i]);
-		gb_connection_destroy(audio->data_connection[i]);
-	}
+	mutex_lock(&gb_codec_list_lock);
+	list_del(&gbcodec->list);
+	/* inform uevent to above layers */
+	gb_audio_manager_remove(gbcodec->manager_id);
 
-	gbaudio_codec_remove(audio->mgmt_connection);
-	gb_connection_destroy(audio->mgmt_connection);
+	mutex_lock(&gbcodec->lock);
+	list_for_each_entry_safe(dai, _dai, &gbcodec->dai_list, list)
+		gb_connection_disable(dai->connection);
+	gbaudio_unregister_codec(gbcodec);
 
-	kfree(audio);
+	list_for_each_entry_safe(dai, _dai, &gbcodec->dai_list, list) {
+		gb_connection_destroy(dai->connection);
+		list_del(&dai->list);
+		devm_kfree(gbcodec->dev, dai);
+	}
+	gb_connection_destroy(gbcodec->mgmt_connection);
+	gbcodec->mgmt_connection = NULL;
+	mutex_unlock(&gbcodec->lock);
+
+	devm_kfree(&bundle->dev, gbcodec);
+	mutex_unlock(&gb_codec_list_lock);
 }
 
 static const struct greybus_bundle_id gb_audio_id_table[] = {
diff --git a/drivers/staging/greybus/audio_codec.h b/drivers/staging/greybus/audio_codec.h
index bba48a59bf4d4..56110913b70e7 100644
--- a/drivers/staging/greybus/audio_codec.h
+++ b/drivers/staging/greybus/audio_codec.h
@@ -84,6 +84,8 @@ struct gbaudio_control {
 struct gbaudio_dai {
 	__le16 data_cport;
 	char name[NAME_SIZE];
+	/* DAI users */
+	atomic_t users;
 	struct gb_connection *connection;
 	struct list_head list;
 };
@@ -116,8 +118,9 @@ struct gbaudio_codec_info {
 	char *dailink_name[MAX_DAIS];
 	int num_dai_links;
 
-	/* topology related */
 	struct gb_connection *mgmt_connection;
+	size_t num_data_connections;
+	/* topology related */
 	int num_dais;
 	int num_kcontrols;
 	int num_dapm_widgets;
@@ -131,9 +134,6 @@ struct gbaudio_codec_info {
 	struct snd_soc_dapm_route *routes;
 	struct snd_soc_dai_driver *dais;
 
-	/* codec users */
-	atomic_t users;
-
 	/* lists */
 	struct list_head dai_list;
 	struct list_head widget_list;
@@ -142,17 +142,8 @@ struct gbaudio_codec_info {
 	struct mutex lock;
 };
 
-struct gb_audio {
-	struct gb_connection		*mgmt_connection;
-	size_t				num_data_connections;
-	struct gbaudio_codec_info	*gbcodec;
-	struct gb_connection		*data_connection[0];
-};
-
-struct gbaudio_dai *gbaudio_add_dai(struct gbaudio_codec_info *gbcodec,
-				    int data_cport,
-				    struct gb_connection *connection,
-				    const char *name);
+struct gbaudio_dai *gbaudio_find_dai(struct gbaudio_codec_info *gbcodec,
+				     int data_cport, const char *name);
 int gbaudio_tplg_parse_data(struct gbaudio_codec_info *gbcodec,
 			       struct gb_audio_topology *tplg_data);
 void gbaudio_tplg_release(struct gbaudio_codec_info *gbcodec);
diff --git a/drivers/staging/greybus/audio_topology.c b/drivers/staging/greybus/audio_topology.c
index 90d2148392ef7..5fab393130a59 100644
--- a/drivers/staging/greybus/audio_topology.c
+++ b/drivers/staging/greybus/audio_topology.c
@@ -92,8 +92,7 @@ static int gbcodec_mixer_ctl_info(struct snd_kcontrol *kcontrol,
 	struct gbaudio_ctl_pvt *data;
 	struct gb_audio_ctl_elem_info *info;
 	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
-	struct gb_audio *audio = snd_soc_codec_get_drvdata(codec);
-	struct gbaudio_codec_info *gbcodec = audio->gbcodec;
+	struct gbaudio_codec_info *gbcodec = snd_soc_codec_get_drvdata(codec);
 
 	data = (struct gbaudio_ctl_pvt *)kcontrol->private_value;
 	info = (struct gb_audio_ctl_elem_info *)data->info;
@@ -139,8 +138,7 @@ static int gbcodec_mixer_ctl_get(struct snd_kcontrol *kcontrol,
 	struct gbaudio_ctl_pvt *data;
 	struct gb_audio_ctl_elem_value gbvalue;
 	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
-	struct gb_audio *audio = snd_soc_codec_get_drvdata(codec);
-	struct gbaudio_codec_info *gb = audio->gbcodec;
+	struct gbaudio_codec_info *gb = snd_soc_codec_get_drvdata(codec);
 
 	data = (struct gbaudio_ctl_pvt *)kcontrol->private_value;
 	info = (struct gb_audio_ctl_elem_info *)data->info;
@@ -187,8 +185,7 @@ static int gbcodec_mixer_ctl_put(struct snd_kcontrol *kcontrol,
 	struct gbaudio_ctl_pvt *data;
 	struct gb_audio_ctl_elem_value gbvalue;
 	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
-	struct gb_audio *audio = snd_soc_codec_get_drvdata(codec);
-	struct gbaudio_codec_info *gb = audio->gbcodec;
+	struct gbaudio_codec_info *gb = snd_soc_codec_get_drvdata(codec);
 
 	data = (struct gbaudio_ctl_pvt *)kcontrol->private_value;
 	info = (struct gb_audio_ctl_elem_info *)data->info;
@@ -282,8 +279,7 @@ static int gbcodec_mixer_dapm_ctl_get(struct snd_kcontrol *kcontrol,
 	struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol);
 	struct snd_soc_dapm_widget *widget = wlist->widgets[0];
 	struct snd_soc_codec *codec = widget->codec;
-	struct gb_audio *audio = snd_soc_codec_get_drvdata(codec);
-	struct gbaudio_codec_info *gb = audio->gbcodec;
+	struct gbaudio_codec_info *gb = snd_soc_codec_get_drvdata(codec);
 
 	data = (struct gbaudio_ctl_pvt *)kcontrol->private_value;
 	info = (struct gb_audio_ctl_elem_info *)data->info;
@@ -317,8 +313,7 @@ static int gbcodec_mixer_dapm_ctl_put(struct snd_kcontrol *kcontrol,
 	struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol);
 	struct snd_soc_dapm_widget *widget = wlist->widgets[0];
 	struct snd_soc_codec *codec = widget->codec;
-	struct gb_audio *audio = snd_soc_codec_get_drvdata(codec);
-	struct gbaudio_codec_info *gb = audio->gbcodec;
+	struct gbaudio_codec_info *gb = snd_soc_codec_get_drvdata(codec);
 
 	data = (struct gbaudio_ctl_pvt *)kcontrol->private_value;
 	info = (struct gb_audio_ctl_elem_info *)data->info;
@@ -524,8 +519,7 @@ static int gbaudio_widget_event(struct snd_soc_dapm_widget *w,
 	int wid;
 	int ret;
 	struct snd_soc_codec *codec = w->codec;
-	struct gb_audio *audio = snd_soc_codec_get_drvdata(codec);
-	struct gbaudio_codec_info *gbcodec = audio->gbcodec;
+	struct gbaudio_codec_info *gbcodec = snd_soc_codec_get_drvdata(codec);
 
 	dev_dbg(codec->dev, "%s %s %d\n", __func__, w->name, event);
 
@@ -819,9 +813,9 @@ static int gbaudio_tplg_process_dais(struct gbaudio_codec_info *gbcodec,
 	int i, ret;
 	struct snd_soc_dai_driver *gb_dais;
 	struct gb_audio_dai *curr;
-	struct gbaudio_dai *dai, *_dai;
 	size_t size;
 	char dai_name[NAME_SIZE];
+	struct gbaudio_dai *dai;
 
 	size = sizeof(struct snd_soc_dai_driver) * gbcodec->num_dais;
 	gb_dais = devm_kzalloc(gbcodec->dev, size, GFP_KERNEL);
@@ -839,10 +833,10 @@ static int gbaudio_tplg_process_dais(struct gbaudio_codec_info *gbcodec,
 		/* append dev_id to dai_name */
 		snprintf(dai_name, NAME_SIZE, "%s.%d", curr->name,
 			 gbcodec->dev_id);
-		dai = gbaudio_add_dai(gbcodec, curr->data_cport, NULL,
-				      dai_name);
+		dai = gbaudio_find_dai(gbcodec, curr->data_cport, NULL);
 		if (!dai)
 			goto error;
+		strlcpy(dai->name, dai_name, NAME_SIZE);
 		dev_dbg(gbcodec->dev, "%s:DAI added\n", dai->name);
 		gb_dais[i].name = dai->name;
 		curr++;
@@ -852,10 +846,6 @@ static int gbaudio_tplg_process_dais(struct gbaudio_codec_info *gbcodec,
 	return 0;
 
 error:
-	list_for_each_entry_safe(dai, _dai, &gbcodec->dai_list, list) {
-		list_del(&dai->list);
-		devm_kfree(gbcodec->dev, dai);
-	}
 	devm_kfree(gbcodec->dev, gb_dais);
 	return ret;
 }
@@ -948,68 +938,6 @@ static int gbaudio_tplg_process_header(struct gbaudio_codec_info *gbcodec,
 	return 0;
 }
 
-static struct gbaudio_dai *gbaudio_allocate_dai(struct gbaudio_codec_info *gb,
-					 int data_cport,
-					 struct gb_connection *connection,
-					 const char *name)
-{
-	struct gbaudio_dai *dai;
-
-	mutex_lock(&gb->lock);
-	dai = devm_kzalloc(gb->dev, sizeof(*dai), GFP_KERNEL);
-	if (!dai) {
-		dev_err(gb->dev, "%s:DAI Malloc failure\n", name);
-		mutex_unlock(&gb->lock);
-		return NULL;
-	}
-
-	dai->data_cport = data_cport;
-	dai->connection = connection;
-
-	/* update name */
-	if (name)
-		strlcpy(dai->name, name, NAME_SIZE);
-	list_add(&dai->list, &gb->dai_list);
-	dev_dbg(gb->dev, "%d:%s: DAI added\n", data_cport, dai->name);
-	mutex_unlock(&gb->lock);
-
-	return dai;
-}
-
-struct gbaudio_dai *gbaudio_add_dai(struct gbaudio_codec_info *gbcodec,
-				    int data_cport,
-				    struct gb_connection *connection,
-				    const char *name)
-{
-	struct gbaudio_dai *dai, *_dai;
-
-	/* FIXME need to take care for multiple DAIs */
-	mutex_lock(&gbcodec->lock);
-	if (list_empty(&gbcodec->dai_list)) {
-		mutex_unlock(&gbcodec->lock);
-		return gbaudio_allocate_dai(gbcodec, data_cport, connection,
-					    name);
-	}
-
-	list_for_each_entry_safe(dai, _dai, &gbcodec->dai_list, list) {
-		if (dai->data_cport == data_cport) {
-			if (connection)
-				dai->connection = connection;
-
-			if (name)
-				strlcpy(dai->name, name, NAME_SIZE);
-			dev_dbg(gbcodec->dev, "%d:%s: DAI updated\n",
-				data_cport, dai->name);
-			mutex_unlock(&gbcodec->lock);
-			return dai;
-		}
-	}
-
-	dev_err(gbcodec->dev, "%s:DAI not found\n", name);
-	mutex_unlock(&gbcodec->lock);
-	return NULL;
-}
-
 int gbaudio_tplg_parse_data(struct gbaudio_codec_info *gbcodec,
 			       struct gb_audio_topology *tplg_data)
 {
@@ -1074,7 +1002,6 @@ int gbaudio_tplg_parse_data(struct gbaudio_codec_info *gbcodec,
 
 void gbaudio_tplg_release(struct gbaudio_codec_info *gbcodec)
 {
-	struct gbaudio_dai *dai, *_dai;
 	struct gbaudio_control *control, *_control;
 	struct gbaudio_widget *widget, *_widget;
 
@@ -1109,12 +1036,4 @@ void gbaudio_tplg_release(struct gbaudio_codec_info *gbcodec)
 	/* release routes */
 	if (gbcodec->routes)
 		devm_kfree(gbcodec->dev, gbcodec->routes);
-
-	/* release DAIs */
-	mutex_lock(&gbcodec->lock);
-	list_for_each_entry_safe(dai, _dai, &gbcodec->dai_list, list) {
-		list_del(&dai->list);
-		devm_kfree(gbcodec->dev, dai);
-	}
-	mutex_unlock(&gbcodec->lock);
 }
-- 
2.30.2