From 9822b4c90d77e3c6555fb21c459c4a61c6a8619f Mon Sep 17 00:00:00 2001 From: Ranjani Sridharan Date: Wed, 16 Oct 2024 11:29:07 +0800 Subject: ASoC: SOF: ipc4-topology: Do not set ALH node_id for aggregated DAIs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For aggregated DAIs, the node ID is set to the group_id during the DAI widget's ipc_prepare op. With the current logic, setting the dai_index for node_id in the dai_config is redundant as it will be overwritten with the group_id anyway. Removing it will also prevent any accidental clearing/resetting of the group_id for aggregated DAIs due to the dai_config calls could that happen before the allocated group_id is freed. Signed-off-by: Ranjani Sridharan Reviewed-by: Péter Ujfalusi Reviewed-by: Kai Vehmanen Signed-off-by: Bard Liao All: stable@vger.kernel.org # 6.10.x 6.11.x Link: https://patch.msgid.link/20241016032910.14601-2-yung-chuan.liao@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/ipc4-topology.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/sound/soc/sof/ipc4-topology.c b/sound/soc/sof/ipc4-topology.c index 87be7f16e8c2..240fee2166d1 100644 --- a/sound/soc/sof/ipc4-topology.c +++ b/sound/soc/sof/ipc4-topology.c @@ -3129,9 +3129,20 @@ static int sof_ipc4_dai_config(struct snd_sof_dev *sdev, struct snd_sof_widget * * group_id during copier's ipc_prepare op. */ if (flags & SOF_DAI_CONFIG_FLAGS_HW_PARAMS) { + struct sof_ipc4_alh_configuration_blob *blob; + + blob = (struct sof_ipc4_alh_configuration_blob *)ipc4_copier->copier_config; ipc4_copier->dai_index = data->dai_node_id; - copier_data->gtw_cfg.node_id &= ~SOF_IPC4_NODE_INDEX_MASK; - copier_data->gtw_cfg.node_id |= SOF_IPC4_NODE_INDEX(data->dai_node_id); + + /* + * no need to set the node_id for aggregated DAI's. These will be assigned + * a group_id during widget ipc_prepare + */ + if (blob->alh_cfg.device_count == 1) { + copier_data->gtw_cfg.node_id &= ~SOF_IPC4_NODE_INDEX_MASK; + copier_data->gtw_cfg.node_id |= + SOF_IPC4_NODE_INDEX(data->dai_node_id); + } } break; -- cgit From 6e38a7e098d32d128b00b42a536151de9ea1340b Mon Sep 17 00:00:00 2001 From: Ranjani Sridharan Date: Wed, 16 Oct 2024 11:29:08 +0800 Subject: ASoC: SOF: Intel: hda: Handle prepare without close for non-HDA DAI's MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When a PCM is restarted after a snd_pcm_drain/snd_pcm_drop(), the prepare callback will be invoked and the hw_params will be set again. For the HDA DAI's, the hw_params function handles this case already but not for the non-HDA DAI's. So, add the check for link_prepared to verify if the hw_params should be done again or not. Additionally, for SDW DAI's reset the PCMSyCM registers as would be done in the case of a start after a hw_free. Signed-off-by: Ranjani Sridharan Reviewed-by: Péter Ujfalusi Reviewed-by: Kai Vehmanen Signed-off-by: Bard Liao All: stable@vger.kernel.org # 6.10.x 6.11.x Link: https://patch.msgid.link/20241016032910.14601-3-yung-chuan.liao@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda-dai.c | 36 ++++++++++++++++++++++++++++++++---- 1 file changed, 32 insertions(+), 4 deletions(-) diff --git a/sound/soc/sof/intel/hda-dai.c b/sound/soc/sof/intel/hda-dai.c index 1c823f9eea57..8cccf38967e7 100644 --- a/sound/soc/sof/intel/hda-dai.c +++ b/sound/soc/sof/intel/hda-dai.c @@ -370,6 +370,13 @@ static int non_hda_dai_hw_params_data(struct snd_pcm_substream *substream, return -EINVAL; } + sdev = widget_to_sdev(w); + hext_stream = ops->get_hext_stream(sdev, cpu_dai, substream); + + /* nothing more to do if the link is already prepared */ + if (hext_stream && hext_stream->link_prepared) + return 0; + /* use HDaudio stream handling */ ret = hda_dai_hw_params_data(substream, params, cpu_dai, data, flags); if (ret < 0) { @@ -377,7 +384,6 @@ static int non_hda_dai_hw_params_data(struct snd_pcm_substream *substream, return ret; } - sdev = widget_to_sdev(w); if (sdev->dspless_mode_selected) return 0; @@ -482,6 +488,31 @@ int sdw_hda_dai_hw_params(struct snd_pcm_substream *substream, int ret; int i; + ops = hda_dai_get_ops(substream, cpu_dai); + if (!ops) { + dev_err(cpu_dai->dev, "DAI widget ops not set\n"); + return -EINVAL; + } + + sdev = widget_to_sdev(w); + hext_stream = ops->get_hext_stream(sdev, cpu_dai, substream); + + /* nothing more to do if the link is already prepared */ + if (hext_stream && hext_stream->link_prepared) + return 0; + + /* + * reset the PCMSyCM registers to handle a prepare callback when the PCM is restarted + * due to xruns or after a call to snd_pcm_drain/drop() + */ + ret = hdac_bus_eml_sdw_map_stream_ch(sof_to_bus(sdev), link_id, cpu_dai->id, + 0, 0, substream->stream); + if (ret < 0) { + dev_err(cpu_dai->dev, "%s: hdac_bus_eml_sdw_map_stream_ch failed %d\n", + __func__, ret); + return ret; + } + data.dai_index = (link_id << 8) | cpu_dai->id; data.dai_node_id = intel_alh_id; ret = non_hda_dai_hw_params_data(substream, params, cpu_dai, &data, flags); @@ -490,10 +521,7 @@ int sdw_hda_dai_hw_params(struct snd_pcm_substream *substream, return ret; } - ops = hda_dai_get_ops(substream, cpu_dai); - sdev = widget_to_sdev(w); hext_stream = ops->get_hext_stream(sdev, cpu_dai, substream); - if (!hext_stream) return -ENODEV; -- cgit From c78f1e15e46ac82607eed593b22992fd08644d96 Mon Sep 17 00:00:00 2001 From: Ranjani Sridharan Date: Wed, 16 Oct 2024 11:29:09 +0800 Subject: soundwire: intel_ace2x: Send PDI stream number during prepare MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In the case of a prepare callback after an xrun or when the PCM is restarted after a call to snd_pcm_drain/snd_pcm_drop, avoid reprogramming the SHIM registers but send the PDI stream number so that the link DMA data can be set. This is needed for the case that the DMA data is cleared when the PCM is stopped and restarted without being closed. Link: https://github.com/thesofproject/sof/issues/9502 Signed-off-by: Ranjani Sridharan Reviewed-by: Péter Ujfalusi Reviewed-by: Kai Vehmanen Signed-off-by: Bard Liao Acked-by: Vinod Koul All: stable@vger.kernel.org # 6.10.x 6.11.x Link: https://patch.msgid.link/20241016032910.14601-4-yung-chuan.liao@linux.intel.com Signed-off-by: Mark Brown --- drivers/soundwire/intel_ace2x.c | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/drivers/soundwire/intel_ace2x.c b/drivers/soundwire/intel_ace2x.c index fff312c6968d..4f3dd70d6a1a 100644 --- a/drivers/soundwire/intel_ace2x.c +++ b/drivers/soundwire/intel_ace2x.c @@ -376,11 +376,12 @@ static int intel_hw_params(struct snd_pcm_substream *substream, static int intel_prepare(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); struct sdw_cdns *cdns = snd_soc_dai_get_drvdata(dai); struct sdw_intel *sdw = cdns_to_intel(cdns); struct sdw_cdns_dai_runtime *dai_runtime; + struct snd_pcm_hw_params *hw_params; int ch, dir; - int ret = 0; dai_runtime = cdns->dai_runtime_array[dai->id]; if (!dai_runtime) { @@ -389,12 +390,8 @@ static int intel_prepare(struct snd_pcm_substream *substream, return -EIO; } + hw_params = &rtd->dpcm[substream->stream].hw_params; if (dai_runtime->suspended) { - struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); - struct snd_pcm_hw_params *hw_params; - - hw_params = &rtd->dpcm[substream->stream].hw_params; - dai_runtime->suspended = false; /* @@ -415,15 +412,11 @@ static int intel_prepare(struct snd_pcm_substream *substream, /* the SHIM will be configured in the callback functions */ sdw_cdns_config_stream(cdns, ch, dir, dai_runtime->pdi); - - /* Inform DSP about PDI stream number */ - ret = intel_params_stream(sdw, substream, dai, - hw_params, - sdw->instance, - dai_runtime->pdi->intel_alh_id); } - return ret; + /* Inform DSP about PDI stream number */ + return intel_params_stream(sdw, substream, dai, hw_params, sdw->instance, + dai_runtime->pdi->intel_alh_id); } static int -- cgit From ab5593793e9088abcddce30ba8e376e31b7285fd Mon Sep 17 00:00:00 2001 From: Ranjani Sridharan Date: Wed, 16 Oct 2024 11:29:10 +0800 Subject: ASoC: SOF: Intel: hda: Always clean up link DMA during stop MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is required to reset the DMA read/write pointers when the stream is prepared and restarted after a call to snd_pcm_drain()/snd_pcm_drop(). Also, now that the stream is reset during stop, do not save LLP registers in the case of STOP/suspend to avoid erroneous delay reporting. Link: https://github.com/thesofproject/sof/issues/9502 Signed-off-by: Ranjani Sridharan Reviewed-by: Péter Ujfalusi Reviewed-by: Kai Vehmanen Signed-off-by: Bard Liao All: stable@vger.kernel.org # 6.10.x 6.11.x Link: https://patch.msgid.link/20241016032910.14601-5-yung-chuan.liao@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda-dai-ops.c | 23 ++++++++++------------- sound/soc/sof/intel/hda-dai.c | 1 + 2 files changed, 11 insertions(+), 13 deletions(-) diff --git a/sound/soc/sof/intel/hda-dai-ops.c b/sound/soc/sof/intel/hda-dai-ops.c index 484c76147885..92681ca7f24d 100644 --- a/sound/soc/sof/intel/hda-dai-ops.c +++ b/sound/soc/sof/intel/hda-dai-ops.c @@ -346,20 +346,21 @@ static int hda_trigger(struct snd_sof_dev *sdev, struct snd_soc_dai *cpu_dai, case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: snd_hdac_ext_stream_start(hext_stream); break; - case SNDRV_PCM_TRIGGER_SUSPEND: - case SNDRV_PCM_TRIGGER_STOP: case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - snd_hdac_ext_stream_clear(hext_stream); - /* - * Save the LLP registers in case the stream is - * restarting due PAUSE_RELEASE, or START without a pcm - * close/open since in this case the LLP register is not reset - * to 0 and the delay calculation will return with invalid - * results. + * Save the LLP registers since in case of PAUSE the LLP + * register are not reset to 0, the delay calculation will use + * the saved offsets for compensating the delay calculation. */ hext_stream->pplcllpl = readl(hext_stream->pplc_addr + AZX_REG_PPLCLLPL); hext_stream->pplcllpu = readl(hext_stream->pplc_addr + AZX_REG_PPLCLLPU); + snd_hdac_ext_stream_clear(hext_stream); + break; + case SNDRV_PCM_TRIGGER_SUSPEND: + case SNDRV_PCM_TRIGGER_STOP: + hext_stream->pplcllpl = 0; + hext_stream->pplcllpu = 0; + snd_hdac_ext_stream_clear(hext_stream); break; default: dev_err(sdev->dev, "unknown trigger command %d\n", cmd); @@ -512,7 +513,6 @@ static const struct hda_dai_widget_dma_ops sdw_ipc4_chain_dma_ops = { static int hda_ipc3_post_trigger(struct snd_sof_dev *sdev, struct snd_soc_dai *cpu_dai, struct snd_pcm_substream *substream, int cmd) { - struct hdac_ext_stream *hext_stream = hda_get_hext_stream(sdev, cpu_dai, substream); struct snd_soc_dapm_widget *w = snd_soc_dai_get_widget(cpu_dai, substream->stream); switch (cmd) { @@ -527,9 +527,6 @@ static int hda_ipc3_post_trigger(struct snd_sof_dev *sdev, struct snd_soc_dai *c if (ret < 0) return ret; - if (cmd == SNDRV_PCM_TRIGGER_STOP) - return hda_link_dma_cleanup(substream, hext_stream, cpu_dai); - break; } case SNDRV_PCM_TRIGGER_PAUSE_PUSH: diff --git a/sound/soc/sof/intel/hda-dai.c b/sound/soc/sof/intel/hda-dai.c index 8cccf38967e7..ac505c7ad342 100644 --- a/sound/soc/sof/intel/hda-dai.c +++ b/sound/soc/sof/intel/hda-dai.c @@ -302,6 +302,7 @@ static int __maybe_unused hda_dai_trigger(struct snd_pcm_substream *substream, i } switch (cmd) { + case SNDRV_PCM_TRIGGER_STOP: case SNDRV_PCM_TRIGGER_SUSPEND: ret = hda_link_dma_cleanup(substream, hext_stream, dai); if (ret < 0) { -- cgit