From 7e424ae1cc3488ccc64de0017d5bca7e57860881 Mon Sep 17 00:00:00 2001 From: Shuai Li Date: Tue, 4 Jun 2019 13:41:43 +0800 Subject: [PATCH] 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 --- sound/soc/amlogic/auge/ddr_mngr.c | 36 ++++++++++++++++++++++++++++++------ sound/soc/amlogic/auge/ddr_mngr.h | 1 + sound/soc/amlogic/auge/extn.c | 9 +++++++-- sound/soc/amlogic/auge/loopback.c | 11 +++++++++-- sound/soc/amlogic/auge/pdm.c | 12 +++++++++--- sound/soc/amlogic/auge/spdif.c | 11 +++++++++-- sound/soc/amlogic/auge/tdm.c | 11 +++++++++-- 7 files changed, 74 insertions(+), 17 deletions(-) diff --git a/sound/soc/amlogic/auge/ddr_mngr.c b/sound/soc/amlogic/auge/ddr_mngr.c index deae7d1..ecb7293 100644 --- a/sound/soc/amlogic/auge/ddr_mngr.c +++ b/sound/soc/amlogic/auge/ddr_mngr.c @@ -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) { diff --git a/sound/soc/amlogic/auge/ddr_mngr.h b/sound/soc/amlogic/auge/ddr_mngr.h index a47a002..c3e9c7b 100644 --- a/sound/soc/amlogic/auge/ddr_mngr.h +++ b/sound/soc/amlogic/auge/ddr_mngr.h @@ -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, diff --git a/sound/soc/amlogic/auge/extn.c b/sound/soc/amlogic/auge/extn.c index d414ddda..a5fd642 100644 --- a/sound/soc/amlogic/auge/extn.c +++ b/sound/soc/amlogic/auge/extn.c @@ -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: diff --git a/sound/soc/amlogic/auge/loopback.c b/sound/soc/amlogic/auge/loopback.c index 31fe198..767f720 100644 --- a/sound/soc/amlogic/auge/loopback.c +++ b/sound/soc/amlogic/auge/loopback.c @@ -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: diff --git a/sound/soc/amlogic/auge/pdm.c b/sound/soc/amlogic/auge/pdm.c index bc90f43..b1c3e57 100644 --- a/sound/soc/amlogic/auge/pdm.c +++ b/sound/soc/amlogic/auge/pdm.c @@ -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: diff --git a/sound/soc/amlogic/auge/spdif.c b/sound/soc/amlogic/auge/spdif.c index 375a3a0..9886dc7 100644 --- a/sound/soc/amlogic/auge/spdif.c +++ b/sound/soc/amlogic/auge/spdif.c @@ -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; diff --git a/sound/soc/amlogic/auge/tdm.c b/sound/soc/amlogic/auge/tdm.c index 50b94c3..1cca38e2 100644 --- a/sound/soc/amlogic/auge/tdm.c +++ b/sound/soc/amlogic/auge/tdm.c @@ -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; -- 2.7.4