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)
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)
{
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,
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:
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 */
/* 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:
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:
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;
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;