ASoC: msm-cpe: Fix sequence for data channel teardown

The data channel for buffering has two endpoints, one on the MSM and
another on the codec. When codec endpoint is torn down, it waits for an
interrupt for channel teardown from hardware. But, since MSM endpoint is
still connected, the interrupt is never receieved and the codec wait
gets timed out. This adds delay in data channel teardown. Fix this issue
by making sure the MSM endpoint is torn down first and then the codec
endpoint gets torn down.

CRs-fixed: 940132
Change-Id: Ie6529e9269aa29fb3d312b816c3d83e9e3e6e10e
Signed-off-by: Bhalchandra Gajare <gajare@codeaurora.org>
This commit is contained in:
Bhalchandra Gajare 2015-12-22 18:02:32 -08:00 committed by Gerrit - the friendly Code Review server
parent b9d096ab5e
commit 7a75d9ed2a
3 changed files with 47 additions and 14 deletions

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2014, The Linux Foundation. All rights reserved.
* Copyright (c) 2014,2016, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@ -16,6 +16,12 @@
#include <linux/slimbus/slimbus.h>
enum msm_dai_slim_event {
MSM_DAI_SLIM_ENABLE = 1,
MSM_DAI_SLIM_PRE_DISABLE,
MSM_DAI_SLIM_DISABLE,
};
/*
* struct msm_slim_dma_data - DMA data for slimbus data transfer
*
@ -38,7 +44,8 @@ struct msm_slim_dma_data {
/* Callback for data channel control */
int (*dai_channel_ctl) (struct msm_slim_dma_data *dma_data,
struct snd_soc_dai *dai, bool enable);
struct snd_soc_dai *dai,
enum msm_dai_slim_event event);
};
#endif

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013-2015, Linux Foundation. All rights reserved.
* Copyright (c) 2013-2016, Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@ -392,6 +392,14 @@ static int msm_cpe_lsm_lab_stop(struct snd_pcm_substream *substream)
}
}
rc = dma_data->dai_channel_ctl(dma_data, rtd->cpu_dai,
MSM_DAI_SLIM_PRE_DISABLE);
if (rc)
dev_err(rtd->dev,
"%s: PRE_DISABLE failed, err = %d\n",
__func__, rc);
/* continue with teardown even if any intermediate step fails */
rc = lsm_ops->lab_ch_setup(cpe->core_handle,
session,
WCD_CPE_PRE_DISABLE);
@ -399,11 +407,13 @@ static int msm_cpe_lsm_lab_stop(struct snd_pcm_substream *substream)
dev_err(rtd->dev,
"%s: PRE ch teardown failed, err = %d\n",
__func__, rc);
/* continue with teardown even if any intermediate step fails */
rc = dma_data->dai_channel_ctl(dma_data, rtd->cpu_dai, false);
rc = dma_data->dai_channel_ctl(dma_data, rtd->cpu_dai,
MSM_DAI_SLIM_DISABLE);
if (rc)
dev_err(rtd->dev,
"%s: open data failed %d\n", __func__, rc);
"%s: DISABLE failed, err = %d\n",
__func__, rc);
dma_data->ph = 0;
/*
@ -616,7 +626,8 @@ static int msm_cpe_lab_thread(void *data)
goto done;
}
rc = dma_data->dai_channel_ctl(dma_data, rtd->cpu_dai, true);
rc = dma_data->dai_channel_ctl(dma_data, rtd->cpu_dai,
MSM_DAI_SLIM_ENABLE);
if (rc) {
dev_err(rtd->dev,
"%s: open data failed %d\n", __func__, rc);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2014-2015, The Linux Foundation. All rights reserved.
* Copyright (c) 2014-2016, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@ -89,7 +89,8 @@ struct msm_slim_dai_data *msm_slim_get_dai_data(
}
static int msm_dai_slim_ch_ctl(struct msm_slim_dma_data *dma_data,
struct snd_soc_dai *dai, bool enable)
struct snd_soc_dai *dai,
enum msm_dai_slim_event event)
{
struct slim_device *sdev;
struct msm_dai_slim_drv_data *drv_data;
@ -114,11 +115,12 @@ static int msm_dai_slim_ch_ctl(struct msm_slim_dma_data *dma_data,
}
dev_dbg(&sdev->dev,
"%s: enable = %s, rate = %u\n", __func__,
enable ? "true" : "false",
dai_data->rate);
"%s: event = 0x%x, rate = %u\n", __func__,
event, dai_data->rate);
switch (event) {
case MSM_DAI_SLIM_ENABLE:
if (enable) {
if (!(dai_data->status & DAI_STATE_PREPARED)) {
dev_err(&sdev->dev,
"%s: dai id (%d) has invalid state 0x%x\n",
@ -171,7 +173,9 @@ static int msm_dai_slim_ch_ctl(struct msm_slim_dma_data *dma_data,
}
/* Mark dai status as running */
SET_DAI_STATE(dai_data->status, DAI_STATE_RUNNING);
} else {
break;
case MSM_DAI_SLIM_PRE_DISABLE:
if (!(dai_data->status & DAI_STATE_RUNNING)) {
dev_err(&sdev->dev,
"%s: dai id (%d) has invalid state 0x%x\n",
@ -188,6 +192,9 @@ static int msm_dai_slim_ch_ctl(struct msm_slim_dma_data *dma_data,
__func__, rc);
goto done;
}
break;
case MSM_DAI_SLIM_DISABLE:
rc = slim_dealloc_mgrports(sdev,
&dma_data->ph, 1);
@ -199,6 +206,14 @@ static int msm_dai_slim_ch_ctl(struct msm_slim_dma_data *dma_data,
}
/* clear running state for dai*/
CLR_DAI_STATE(dai_data->status, DAI_STATE_RUNNING);
break;
default:
dev_err(&sdev->dev,
"%s: Unhandled event 0x%x\n",
__func__, event);
rc = -EINVAL;
goto done;
}
return rc;