audio: audio ABUS stuck issue [1/1]

PD#SWPL-9142

Problem:
Audio Abus may be stuck if it is stopped
when the burst is not finished.
And the stuck can't be recovered
unless reboot the system.

Solution:
Add check to make sure that the transfer
is over then start to disable the toddr fifo.

Verify:
TL1 stress test.

Change-Id: I28dcf84ddec421bc70370b2544f0bf1f3272e7b4
Signed-off-by: Shuai Li <shuai.li@amlogic.com>
This commit is contained in:
Shuai Li
2019-06-04 13:41:43 +08:00
committed by Luan Yuan
parent e5c62b37e8
commit df90d2a79a
7 changed files with 74 additions and 17 deletions

View File

@@ -285,12 +285,7 @@ int aml_toddr_set_intrpt(struct toddr *to, unsigned int intrpt)
unsigned int aml_toddr_get_position(struct toddr *to)
{
struct aml_audio_controller *actrl = to->actrl;
unsigned int reg_base = to->reg_base;
unsigned int reg;
reg = calc_toddr_address(EE_AUDIO_TODDR_A_STATUS2, reg_base);
return aml_audiobus_read(actrl, reg);
return aml_toddr_read_status2(to);
}
unsigned int aml_toddr_get_addr(struct toddr *to, enum status_sel sel)
@@ -528,6 +523,35 @@ unsigned int aml_toddr_read_status2(struct toddr *to)
return aml_audiobus_read(actrl, reg);
}
bool aml_toddr_burst_finished(struct toddr *to)
{
unsigned int addr_request, addr_reply, i = 0;
struct aml_audio_controller *actrl = to->actrl;
unsigned int reg_base = to->reg_base;
unsigned int reg;
/* max 200us delay */
for (i = 0; i < 200; i++) {
reg = calc_toddr_address(EE_AUDIO_TODDR_A_CTRL1, reg_base);
aml_audiobus_update_bits(actrl, reg, 0xf << 8, 0x0 << 8);
addr_request = aml_toddr_get_position(to);
reg = calc_toddr_address(EE_AUDIO_TODDR_A_CTRL1, reg_base);
aml_audiobus_update_bits(actrl, reg, 0xf << 8, 0x2 << 8);
addr_reply = aml_toddr_get_position(to);
if (addr_request == addr_reply)
return true;
udelay(1);
pr_debug("delay:[%dus]; FRDDR_STATUS2: [0x%x] [0x%x]\n",
i, addr_request, addr_reply);
}
pr_err("Error: 200us time out, TODDR_STATUS2: [0x%x] [0x%x]\n",
addr_request, addr_reply);
return false;
}
/* not for tl1 */
static void aml_toddr_set_resample(struct toddr *to, bool enable)
{

View File

@@ -260,6 +260,7 @@ void aml_toddr_write(struct toddr *to, unsigned int val);
unsigned int aml_toddr_read1(struct toddr *to);
void aml_toddr_write1(struct toddr *to, unsigned int val);
unsigned int aml_toddr_read_status2(struct toddr *to);
bool aml_toddr_burst_finished(struct toddr *to);
/* resample */
void aml_set_resample(enum resample_idx id,

View File

@@ -519,14 +519,19 @@ static int extn_dai_trigger(struct snd_pcm_substream *substream, int cmd,
aml_frddr_enable(p_extn->fddr, false);
} else {
dev_info(substream->pcm->card->dev, "External Capture disable\n");
bool toddr_stopped = false;
if (src == FRATV)
fratv_enable(false);
else if (src == FRHDMIRX)
frhdmirx_enable(false);
dev_info(substream->pcm->card->dev, "External Capture disable\n");
aml_toddr_enable(p_extn->tddr, false);
toddr_stopped = aml_toddr_burst_finished(p_extn->tddr);
if (toddr_stopped)
aml_toddr_enable(p_extn->tddr, false);
else
pr_err("%s(), toddr may be stuck\n", __func__);
}
break;
default:

View File

@@ -763,7 +763,8 @@ static int loopback_dai_trigger(
case SNDRV_PCM_TRIGGER_SUSPEND:
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
if (ss->stream == SNDRV_PCM_STREAM_CAPTURE) {
dev_info(ss->pcm->card->dev, "Loopback Capture disable\n");
bool toddr_stopped = false;
pdm_enable(0);
/* loopback */
@@ -771,8 +772,14 @@ static int loopback_dai_trigger(
/* tdminLB */
tdminlb_fifo_enable(false);
tdminlb_enable(p_loopback->datalb_src, false);
dev_info(ss->pcm->card->dev, "Loopback Capture disable\n");
aml_toddr_enable(p_loopback->tddr, false);
toddr_stopped =
aml_toddr_burst_finished(p_loopback->tddr);
if (toddr_stopped)
aml_toddr_enable(p_loopback->tddr, false);
else
pr_err("%s(), toddr may be stuck\n", __func__);
}
break;
default:

View File

@@ -960,16 +960,22 @@ static int aml_pdm_dai_trigger(
case SNDRV_PCM_TRIGGER_SUSPEND:
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
bool toddr_stopped = false;
if (vad_pdm_is_running()
&& pm_audio_is_suspend()) {
/* switch to VAD buffer */
vad_update_buffer(1);
break;
}
dev_info(substream->pcm->card->dev, "pdm capture stop\n");
pdm_enable(0);
aml_toddr_enable(p_pdm->tddr, 0);
dev_info(substream->pcm->card->dev, "pdm capture stop\n");
toddr_stopped = aml_toddr_burst_finished(p_pdm->tddr);
if (toddr_stopped)
aml_toddr_enable(p_pdm->tddr, false);
else
pr_err("%s(), toddr may be stuck\n", __func__);
}
break;
default:

View File

@@ -1294,10 +1294,17 @@ static int aml_dai_spdif_trigger(struct snd_pcm_substream *substream, int cmd,
aml_frddr_check(p_spdif->fddr);
aml_frddr_enable(p_spdif->fddr, 0);
} else {
dev_info(substream->pcm->card->dev, "S/PDIF Capture disable\n");
aml_toddr_enable(p_spdif->tddr, 0);
bool toddr_stopped = false;
aml_spdif_enable(p_spdif->actrl,
substream->stream, p_spdif->id, false);
dev_info(substream->pcm->card->dev, "S/PDIF Capture disable\n");
toddr_stopped = aml_toddr_burst_finished(p_spdif->tddr);
if (toddr_stopped)
aml_toddr_enable(p_spdif->tddr, false);
else
pr_err("%s(), toddr may be stuck\n", __func__);
}
break;

View File

@@ -722,10 +722,17 @@ static int aml_dai_tdm_trigger(struct snd_pcm_substream *substream, int cmd,
aml_frddr_enable(p_tdm->fddr, false);
} else {
dev_info(substream->pcm->card->dev, "tdm capture stop\n");
aml_toddr_enable(p_tdm->tddr, false);
bool toddr_stopped = false;
aml_tdm_enable(p_tdm->actrl,
substream->stream, p_tdm->id, false);
dev_info(substream->pcm->card->dev, "tdm capture stop\n");
toddr_stopped = aml_toddr_burst_finished(p_tdm->tddr);
if (toddr_stopped)
aml_toddr_enable(p_tdm->tddr, false);
else
pr_err("%s(), toddr may be stuck\n", __func__);
}
break;