ASoC: SOF: Intel: hda: Handle prepare without close for non-HDA DAI's

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 <ranjani.sridharan@linux.intel.com>
Reviewed-by: Péter Ujfalusi <peter.ujfalusi@linux.intel.com>
Reviewed-by: Kai Vehmanen <kai.vehmanen@linux.intel.com>
Signed-off-by: Bard Liao <yung-chuan.liao@linux.intel.com>
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 <broonie@kernel.org>
This commit is contained in:
Ranjani Sridharan 2024-10-16 11:29:08 +08:00 committed by Mark Brown
parent 9822b4c90d
commit 6e38a7e098
No known key found for this signature in database
GPG Key ID: 24D68B725D5487D0

View File

@ -370,6 +370,13 @@ static int non_hda_dai_hw_params_data(struct snd_pcm_substream *substream,
return -EINVAL; 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 */ /* use HDaudio stream handling */
ret = hda_dai_hw_params_data(substream, params, cpu_dai, data, flags); ret = hda_dai_hw_params_data(substream, params, cpu_dai, data, flags);
if (ret < 0) { if (ret < 0) {
@ -377,7 +384,6 @@ static int non_hda_dai_hw_params_data(struct snd_pcm_substream *substream,
return ret; return ret;
} }
sdev = widget_to_sdev(w);
if (sdev->dspless_mode_selected) if (sdev->dspless_mode_selected)
return 0; return 0;
@ -482,6 +488,31 @@ int sdw_hda_dai_hw_params(struct snd_pcm_substream *substream,
int ret; int ret;
int i; 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_index = (link_id << 8) | cpu_dai->id;
data.dai_node_id = intel_alh_id; data.dai_node_id = intel_alh_id;
ret = non_hda_dai_hw_params_data(substream, params, cpu_dai, &data, flags); 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; 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); hext_stream = ops->get_hext_stream(sdev, cpu_dai, substream);
if (!hext_stream) if (!hext_stream)
return -ENODEV; return -ENODEV;