Commit 25de3491 authored by Vaibhav Agarwal's avatar Vaibhav Agarwal Committed by Greg Kroah-Hartman

greybus: audio: Cleanup GB protocol connections in case of abrupt codec removal

We need to clean up GB protocl connections, otherwise successive
codec insertions fails repeatedly.

NOTE: As per suggestion, since codec is already removed, one should
not trigger any GB command. It'll cause a delay of atleast TIMEOUT
value.
HOwever, failing to cleanup GB protocol, causes successive module
insertion to fail
Signed-off-by: default avatarVaibhav Agarwal <vaibhav.agarwal@linaro.org>
Signed-off-by: default avatarMark Greer <mgreer@animalcreek.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@google.com>
parent 538ecb5a
...@@ -56,6 +56,9 @@ static int gbcodec_startup(struct snd_pcm_substream *substream, ...@@ -56,6 +56,9 @@ static int gbcodec_startup(struct snd_pcm_substream *substream,
dev_dbg(dai->dev, "Register %s:%d DAI, ret:%d\n", dai->name, cportid, dev_dbg(dai->dev, "Register %s:%d DAI, ret:%d\n", dai->name, cportid,
ret); ret);
if (!ret)
atomic_inc(&gb->users);
return ret; return ret;
} }
...@@ -83,6 +86,8 @@ static void gbcodec_shutdown(struct snd_pcm_substream *substream, ...@@ -83,6 +86,8 @@ static void gbcodec_shutdown(struct snd_pcm_substream *substream,
return; return;
} }
atomic_dec(&gb->users);
/* deactivate rx/tx */ /* deactivate rx/tx */
cportid = gb_dai->connection->intf_cport_id; cportid = gb_dai->connection->intf_cport_id;
...@@ -428,6 +433,7 @@ static struct snd_soc_codec_driver soc_codec_dev_gbcodec = { ...@@ -428,6 +433,7 @@ static struct snd_soc_codec_driver soc_codec_dev_gbcodec = {
.reg_word_size = 1, .reg_word_size = 1,
.idle_bias_off = true, .idle_bias_off = true,
.ignore_pmdown_time = 1,
}; };
/* /*
...@@ -573,6 +579,50 @@ struct device_driver gb_codec_driver = { ...@@ -573,6 +579,50 @@ struct device_driver gb_codec_driver = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
}; };
/* XXX
* since BE DAI path is not yet properly closed from above layer,
* dsp dai.mi2s_dai_data.status_mask is still set to STATUS_PORT_STARTED
* this causes immediate playback/capture to fail in case relevant mixer
* control is not turned OFF
* user need to try once again after failure to recover DSP state.
*/
static void gb_audio_cleanup(struct gbaudio_codec_info *gb)
{
int cportid, ret;
struct gbaudio_dai *gb_dai;
struct gb_connection *connection;
struct device *dev = gb->dev;
list_for_each_entry(gb_dai, &gb->dai_list, list) {
/*
* In case of BE dailink, need to deactivate APBridge
* manually
*/
if (gbaudio_dailink.no_pcm && atomic_read(&gb->users)) {
connection = gb_dai->connection;
/* PB active */
ret = gb_audio_apbridgea_stop_tx(connection, 0);
if (ret)
dev_info(dev, "%d:Failed during APBridge stop_tx\n",
ret);
cportid = connection->intf_cport_id;
ret = gb_audio_gb_deactivate_tx(gb->mgmt_connection,
cportid);
if (ret)
dev_info(dev,
"%d:Failed during deactivate_tx\n",
ret);
cportid = connection->hd_cport_id;
ret = gb_audio_apbridgea_unregister_cport(connection, 0,
cportid);
if (ret)
dev_info(dev, "%d:Failed during unregister cport\n",
ret);
atomic_dec(&gb->users);
}
}
}
static int gbaudio_codec_probe(struct gb_connection *connection) static int gbaudio_codec_probe(struct gb_connection *connection)
{ {
int ret, i; int ret, i;
...@@ -641,6 +691,9 @@ static int gbaudio_codec_probe(struct gb_connection *connection) ...@@ -641,6 +691,9 @@ static int gbaudio_codec_probe(struct gb_connection *connection)
mutex_lock(&gbcodec->lock); mutex_lock(&gbcodec->lock);
gbcodec->codec_registered = 1; gbcodec->codec_registered = 1;
/* codec cleanup related */
atomic_set(&gbcodec->users, 0);
/* inform above layer for uevent */ /* inform above layer for uevent */
if (!gbcodec->set_uevent && if (!gbcodec->set_uevent &&
(gbcodec->dai_added == gbcodec->num_dais)) { (gbcodec->dai_added == gbcodec->num_dais)) {
...@@ -696,6 +749,11 @@ static void gbaudio_codec_remove(struct gb_connection *connection) ...@@ -696,6 +749,11 @@ static void gbaudio_codec_remove(struct gb_connection *connection)
} }
mutex_unlock(&gbcodec->lock); mutex_unlock(&gbcodec->lock);
if (atomic_read(&gbcodec->users)) {
dev_err(dev, "Cleanup Error: BE stream not yet closed\n");
gb_audio_cleanup(gbcodec);
}
msm8994_remove_dailink("msm8994-tomtom-mtp-snd-card", &gbaudio_dailink, msm8994_remove_dailink("msm8994-tomtom-mtp-snd-card", &gbaudio_dailink,
1); 1);
gbaudio_remove_dailinks(gbcodec); gbaudio_remove_dailinks(gbcodec);
......
...@@ -131,6 +131,9 @@ struct gbaudio_codec_info { ...@@ -131,6 +131,9 @@ struct gbaudio_codec_info {
struct snd_soc_dapm_route *routes; struct snd_soc_dapm_route *routes;
struct snd_soc_dai_driver *dais; struct snd_soc_dai_driver *dais;
/* codec users */
atomic_t users;
/* lists */ /* lists */
struct list_head dai_list; struct list_head dai_list;
struct list_head widget_list; struct list_head widget_list;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment