audio: audio ABUS stuck issue [1/1]
authorShuai Li <shuai.li@amlogic.com>
Tue, 4 Jun 2019 05:41:43 +0000 (13:41 +0800)
committerJianxin Pan <jianxin.pan@amlogic.com>
Wed, 5 Jun 2019 05:51:51 +0000 (22:51 -0700)
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>
sound/soc/amlogic/auge/ddr_mngr.c
sound/soc/amlogic/auge/ddr_mngr.h
sound/soc/amlogic/auge/extn.c
sound/soc/amlogic/auge/loopback.c
sound/soc/amlogic/auge/pdm.c
sound/soc/amlogic/auge/spdif.c
sound/soc/amlogic/auge/tdm.c

index deae7d1..ecb7293 100644 (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)
 {
index a47a002..c3e9c7b 100644 (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,
index d414ddd..a5fd642 100644 (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:
index 31fe198..767f720 100644 (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:
index bc90f43..b1c3e57 100644 (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:
index fa3709b..c9cea66 100644 (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;
index 50b94c3..1cca38e 100644 (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;