mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-07 19:30:30 +09:00
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:
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user