From 36f2b8f85bb6da220a431201d6567f9fb977b1da Mon Sep 17 00:00:00 2001 From: Seppo Ingalsuo Date: Mon, 26 Apr 2021 17:18:14 +0300 Subject: [PATCH 1/2] Audio: DAI: Error on attempt to use null pointer This patch adds error handling for case where DAI data pointer to DMA channel is not set. The situation can happen if ASRC tries to set up timestamping before DAI has been prepared. More specifically access to dd->chan->index with NULL in chan caused a DSP panic. Signed-off-by: Seppo Ingalsuo --- src/audio/dai.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/audio/dai.c b/src/audio/dai.c index 44c033671607..5547e7762379 100644 --- a/src/audio/dai.c +++ b/src/audio/dai.c @@ -1150,6 +1150,16 @@ static int dai_position(struct comp_dev *dev, struct sof_ipc_stream_posn *posn) return 0; } +/** + * \brief Get DAI parameters and configure timestamping + * \param[in, out] dev DAI device. + * \return Error code. + * + * This function retrieves various DAI parameters such as type, direction, index, and DMA + * controller information those are needed when configuring HW timestamping. Note that + * DAI must be prepared before this function is used (for DMA information). If not, an error + * is returned. + */ static int dai_ts_config(struct comp_dev *dev) { struct dai_data *dd = comp_get_drvdata(dev); @@ -1157,6 +1167,11 @@ static int dai_ts_config(struct comp_dev *dev) struct sof_ipc_comp_dai *dai = COMP_GET_IPC(dev, sof_ipc_comp_dai); comp_dbg(dev, "dai_ts_config()"); + if (!dd->chan) { + comp_err(dev, "dai_ts_config(), No DMA channel information"); + return -EINVAL; + } + cfg->type = dd->dai->drv->type; cfg->direction = dai->direction; cfg->index = dd->dai->index; From 53eafd48883d781a639823c05f0568917e79add0 Mon Sep 17 00:00:00 2001 From: Seppo Ingalsuo Date: Mon, 26 Apr 2021 17:23:35 +0300 Subject: [PATCH 2/2] Audio: ASRC: Move DAI timestamping setup request to trigger start The asrc_dai_configure_timestamp() caused a DSP panic when called from asrc_prepare(). The reason is that DAI prepare now happens after ASRC prepare. Call from trigger start is after pipeline prepare so it avoids this problem. Fixes: #4068 Signed-off-by: Seppo Ingalsuo --- src/audio/asrc/asrc.c | 57 ++++++++++++++++++++++++------------------- 1 file changed, 32 insertions(+), 25 deletions(-) diff --git a/src/audio/asrc/asrc.c b/src/audio/asrc/asrc.c index 05fc27caefc7..e3c832d75059 100644 --- a/src/audio/asrc/asrc.c +++ b/src/audio/asrc/asrc.c @@ -334,13 +334,6 @@ static int asrc_cmd(struct comp_dev *dev, int cmd, void *data, return ret; } -static int asrc_trigger(struct comp_dev *dev, int cmd) -{ - comp_info(dev, "asrc_trigger()"); - - return comp_set_state(dev, cmd); -} - static int asrc_verify_params(struct comp_dev *dev, struct sof_ipc_stream_params *params) { @@ -527,6 +520,38 @@ static int asrc_dai_get_timestamp(struct comp_data *cd, return cd->dai_dev->drv->ops.dai_ts_get(cd->dai_dev, tsd); } +static int asrc_trigger(struct comp_dev *dev, int cmd) +{ + struct comp_buffer *sinkb; + struct comp_buffer *sourceb; + struct comp_data *cd = comp_get_drvdata(dev); + int ret; + + comp_info(dev, "asrc_trigger()"); + + /* Enable timestamping in pipeline DAI */ + if (cmd == COMP_TRIGGER_START && cd->track_drift) { + sourceb = list_first_item(&dev->bsource_list, struct comp_buffer, sink_list); + sinkb = list_first_item(&dev->bsink_list, struct comp_buffer, source_list); + ret = asrc_dai_find(dev, cd, sinkb, sourceb); + if (ret) { + comp_err(dev, "No DAI found to track"); + cd->track_drift = false; + return ret; + } + + cd->ts_count = 0; + ret = asrc_dai_configure_timestamp(cd); + if (ret) { + comp_err(dev, "No timestamp capability in DAI"); + cd->track_drift = false; + return ret; + } + } + + return comp_set_state(dev, cmd); +} + static int asrc_prepare(struct comp_dev *dev) { struct comp_data *cd = comp_get_drvdata(dev); @@ -688,24 +713,6 @@ static int asrc_prepare(struct comp_dev *dev) goto err_free_asrc; } - /* Enable timestamping in pipeline DAI */ - if (cd->track_drift) { - ret = asrc_dai_find(dev, cd, sinkb, sourceb); - if (ret) { - comp_err(dev, "No DAI found to track"); - cd->track_drift = false; - goto err_free_asrc; - } - - cd->ts_count = 0; - ret = asrc_dai_configure_timestamp(cd); - if (ret) { - comp_err(dev, "No timestamp capability in DAI"); - cd->track_drift = false; - goto err_free_asrc; - } - } - return 0; err_free_asrc: