* [PATCH 1/4] ASoC: SOF: Intel: hda-loader: add flag to tag ICCMAX stream
2024-04-04 18:54 [PATCH 0/4] ASoC: SOF: Intel: extend hda-loader for BTP/BRA transfers Pierre-Louis Bossart
@ 2024-04-04 18:54 ` Pierre-Louis Bossart
2024-04-04 18:54 ` [PATCH 2/4] ASoC: SOF: Intel: hda-loader: change signature of code loader helpers Pierre-Louis Bossart
` (3 subsequent siblings)
4 siblings, 0 replies; 6+ messages in thread
From: Pierre-Louis Bossart @ 2024-04-04 18:54 UTC (permalink / raw)
To: linux-sound
Cc: alsa-devel, tiwai, broonie, Pierre-Louis Bossart,
Péter Ujfalusi, Rander Wang, Ranjani Sridharan
The existing code conflates capture stream and ICCMAX stream. This
isn't going to be true any longer when we add support for SDW BPT RX
streams. Add a boolean tag to flag ICCMAX streams.
No functionality change, only future-proofing change.
Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Reviewed-by: Péter Ujfalusi <peter.ujfalusi@linux.intel.com>
Reviewed-by: Rander Wang <rander.wang@intel.com>
Reviewed-by: Ranjani Sridharan <ranjani.sridharan@linux.intel.com>
---
sound/soc/sof/intel/hda-loader.c | 10 +++++-----
sound/soc/sof/intel/hda.h | 2 +-
2 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/sound/soc/sof/intel/hda-loader.c b/sound/soc/sof/intel/hda-loader.c
index d5b9209beb5a..dafb6b3ebb20 100644
--- a/sound/soc/sof/intel/hda-loader.c
+++ b/sound/soc/sof/intel/hda-loader.c
@@ -46,7 +46,7 @@ static void hda_ssp_set_cbp_cfp(struct snd_sof_dev *sdev)
struct hdac_ext_stream *hda_cl_stream_prepare(struct snd_sof_dev *sdev, unsigned int format,
unsigned int size, struct snd_dma_buffer *dmab,
- int direction)
+ int direction, bool is_iccmax)
{
struct hdac_ext_stream *hext_stream;
struct hdac_stream *hstream;
@@ -73,7 +73,7 @@ struct hdac_ext_stream *hda_cl_stream_prepare(struct snd_sof_dev *sdev, unsigned
hstream->format_val = format;
hstream->bufsize = size;
- if (direction == SNDRV_PCM_STREAM_CAPTURE) {
+ if (is_iccmax) {
ret = hda_dsp_iccmax_stream_hw_params(sdev, hext_stream, dmab, NULL);
if (ret < 0) {
dev_err(sdev->dev, "error: iccmax stream prepare failed: %d\n", ret);
@@ -335,7 +335,7 @@ int hda_dsp_cl_boot_firmware_iccmax(struct snd_sof_dev *sdev)
* the data, so use a buffer of PAGE_SIZE for receiving.
*/
iccmax_stream = hda_cl_stream_prepare(sdev, HDA_CL_STREAM_FORMAT, PAGE_SIZE,
- &dmab_bdl, SNDRV_PCM_STREAM_CAPTURE);
+ &dmab_bdl, SNDRV_PCM_STREAM_CAPTURE, true);
if (IS_ERR(iccmax_stream)) {
dev_err(sdev->dev, "error: dma prepare for ICCMAX stream failed\n");
return PTR_ERR(iccmax_stream);
@@ -421,7 +421,7 @@ int hda_dsp_cl_boot_firmware(struct snd_sof_dev *sdev)
/* prepare DMA for code loader stream */
hext_stream = hda_cl_stream_prepare(sdev, HDA_CL_STREAM_FORMAT,
stripped_firmware.size,
- &dmab, SNDRV_PCM_STREAM_PLAYBACK);
+ &dmab, SNDRV_PCM_STREAM_PLAYBACK, false);
if (IS_ERR(hext_stream)) {
dev_err(sdev->dev, "error: dma prepare for fw loading failed\n");
return PTR_ERR(hext_stream);
@@ -538,7 +538,7 @@ int hda_dsp_ipc4_load_library(struct snd_sof_dev *sdev,
/* prepare DMA for code loader stream */
hext_stream = hda_cl_stream_prepare(sdev, HDA_CL_STREAM_FORMAT,
stripped_firmware.size,
- &dmab, SNDRV_PCM_STREAM_PLAYBACK);
+ &dmab, SNDRV_PCM_STREAM_PLAYBACK, false);
if (IS_ERR(hext_stream)) {
dev_err(sdev->dev, "%s: DMA prepare failed\n", __func__);
return PTR_ERR(hext_stream);
diff --git a/sound/soc/sof/intel/hda.h b/sound/soc/sof/intel/hda.h
index 16140ae22c90..30a185d4c7ab 100644
--- a/sound/soc/sof/intel/hda.h
+++ b/sound/soc/sof/intel/hda.h
@@ -705,7 +705,7 @@ int hda_dsp_cl_boot_firmware_iccmax(struct snd_sof_dev *sdev);
int hda_cl_copy_fw(struct snd_sof_dev *sdev, struct hdac_ext_stream *hext_stream);
struct hdac_ext_stream *hda_cl_stream_prepare(struct snd_sof_dev *sdev, unsigned int format,
unsigned int size, struct snd_dma_buffer *dmab,
- int direction);
+ int direction, bool is_iccmax);
int hda_cl_cleanup(struct snd_sof_dev *sdev, struct snd_dma_buffer *dmab,
struct hdac_ext_stream *hext_stream);
int cl_dsp_init(struct snd_sof_dev *sdev, int stream_tag, bool imr_boot);
--
2.40.1
^ permalink raw reply related [flat|nested] 6+ messages in thread* [PATCH 2/4] ASoC: SOF: Intel: hda-loader: change signature of code loader helpers
2024-04-04 18:54 [PATCH 0/4] ASoC: SOF: Intel: extend hda-loader for BTP/BRA transfers Pierre-Louis Bossart
2024-04-04 18:54 ` [PATCH 1/4] ASoC: SOF: Intel: hda-loader: add flag to tag ICCMAX stream Pierre-Louis Bossart
@ 2024-04-04 18:54 ` Pierre-Louis Bossart
2024-04-04 18:54 ` [PATCH 3/4] ASoC: SOF: Intel: don't ignore IOC interrupts for non-audio transfers Pierre-Louis Bossart
` (2 subsequent siblings)
4 siblings, 0 replies; 6+ messages in thread
From: Pierre-Louis Bossart @ 2024-04-04 18:54 UTC (permalink / raw)
To: linux-sound
Cc: alsa-devel, tiwai, broonie, Pierre-Louis Bossart,
Péter Ujfalusi, Rander Wang, Ranjani Sridharan
We need to reuse cl_prepare, cl_trigger and cl_cleanup helpers from a
SoundWire context where only the device information is
available. Rather than pass the 'sdev' argument, use get_drvdata() to
retrieve the required structure.
For consistency, rename hda_cl_stream_prepare() as hda_cl_prepare().
These three helpers are also exported so that they can be referenced
from another module.
Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Reviewed-by: Péter Ujfalusi <peter.ujfalusi@linux.intel.com>
Reviewed-by: Rander Wang <rander.wang@intel.com>
Reviewed-by: Ranjani Sridharan <ranjani.sridharan@linux.intel.com>
---
sound/soc/sof/intel/hda-loader.c | 50 +++++++++++++++++---------------
sound/soc/sof/intel/hda.h | 11 ++++---
2 files changed, 34 insertions(+), 27 deletions(-)
diff --git a/sound/soc/sof/intel/hda-loader.c b/sound/soc/sof/intel/hda-loader.c
index dafb6b3ebb20..5716772a7a91 100644
--- a/sound/soc/sof/intel/hda-loader.c
+++ b/sound/soc/sof/intel/hda-loader.c
@@ -44,13 +44,13 @@ static void hda_ssp_set_cbp_cfp(struct snd_sof_dev *sdev)
}
}
-struct hdac_ext_stream *hda_cl_stream_prepare(struct snd_sof_dev *sdev, unsigned int format,
- unsigned int size, struct snd_dma_buffer *dmab,
- int direction, bool is_iccmax)
+struct hdac_ext_stream *hda_cl_prepare(struct device *dev, unsigned int format,
+ unsigned int size, struct snd_dma_buffer *dmab,
+ int direction, bool is_iccmax)
{
+ struct snd_sof_dev *sdev = dev_get_drvdata(dev);
struct hdac_ext_stream *hext_stream;
struct hdac_stream *hstream;
- struct pci_dev *pci = to_pci_dev(sdev->dev);
int ret;
hext_stream = hda_dsp_stream_get(sdev, direction, 0);
@@ -63,7 +63,7 @@ struct hdac_ext_stream *hda_cl_stream_prepare(struct snd_sof_dev *sdev, unsigned
hstream->substream = NULL;
/* allocate DMA buffer */
- ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV_SG, &pci->dev, size, dmab);
+ ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV_SG, dev, size, dmab);
if (ret < 0) {
dev_err(sdev->dev, "error: memory alloc failed: %d\n", ret);
goto out_put;
@@ -96,6 +96,7 @@ struct hdac_ext_stream *hda_cl_stream_prepare(struct snd_sof_dev *sdev, unsigned
hda_dsp_stream_put(sdev, direction, hstream->stream_tag);
return ERR_PTR(ret);
}
+EXPORT_SYMBOL_NS(hda_cl_prepare, SND_SOC_SOF_INTEL_HDA_COMMON);
/*
* first boot sequence has some extra steps.
@@ -220,9 +221,9 @@ int cl_dsp_init(struct snd_sof_dev *sdev, int stream_tag, bool imr_boot)
return ret;
}
-static int cl_trigger(struct snd_sof_dev *sdev,
- struct hdac_ext_stream *hext_stream, int cmd)
+int hda_cl_trigger(struct device *dev, struct hdac_ext_stream *hext_stream, int cmd)
{
+ struct snd_sof_dev *sdev = dev_get_drvdata(dev);
struct hdac_stream *hstream = &hext_stream->hstream;
int sd_offset = SOF_STREAM_SD_OFFSET(hstream);
@@ -246,10 +247,12 @@ static int cl_trigger(struct snd_sof_dev *sdev,
return hda_dsp_stream_trigger(sdev, hext_stream, cmd);
}
}
+EXPORT_SYMBOL_NS(hda_cl_trigger, SND_SOC_SOF_INTEL_HDA_COMMON);
-int hda_cl_cleanup(struct snd_sof_dev *sdev, struct snd_dma_buffer *dmab,
+int hda_cl_cleanup(struct device *dev, struct snd_dma_buffer *dmab,
struct hdac_ext_stream *hext_stream)
{
+ struct snd_sof_dev *sdev = dev_get_drvdata(dev);
struct hdac_stream *hstream = &hext_stream->hstream;
int sd_offset = SOF_STREAM_SD_OFFSET(hstream);
int ret = 0;
@@ -278,6 +281,7 @@ int hda_cl_cleanup(struct snd_sof_dev *sdev, struct snd_dma_buffer *dmab,
return ret;
}
+EXPORT_SYMBOL_NS(hda_cl_cleanup, SND_SOC_SOF_INTEL_HDA_COMMON);
int hda_cl_copy_fw(struct snd_sof_dev *sdev, struct hdac_ext_stream *hext_stream)
{
@@ -286,7 +290,7 @@ int hda_cl_copy_fw(struct snd_sof_dev *sdev, struct hdac_ext_stream *hext_stream
unsigned int reg;
int ret, status;
- ret = cl_trigger(sdev, hext_stream, SNDRV_PCM_TRIGGER_START);
+ ret = hda_cl_trigger(sdev->dev, hext_stream, SNDRV_PCM_TRIGGER_START);
if (ret < 0) {
dev_err(sdev->dev, "error: DMA trigger start failed\n");
return ret;
@@ -309,7 +313,7 @@ int hda_cl_copy_fw(struct snd_sof_dev *sdev, struct hdac_ext_stream *hext_stream
__func__, chip->rom_status_reg);
}
- ret = cl_trigger(sdev, hext_stream, SNDRV_PCM_TRIGGER_STOP);
+ ret = hda_cl_trigger(sdev->dev, hext_stream, SNDRV_PCM_TRIGGER_STOP);
if (ret < 0) {
dev_err(sdev->dev, "error: DMA trigger stop failed\n");
if (!status)
@@ -334,8 +338,8 @@ int hda_dsp_cl_boot_firmware_iccmax(struct snd_sof_dev *sdev)
* Prepare capture stream for ICCMAX. We do not need to store
* the data, so use a buffer of PAGE_SIZE for receiving.
*/
- iccmax_stream = hda_cl_stream_prepare(sdev, HDA_CL_STREAM_FORMAT, PAGE_SIZE,
- &dmab_bdl, SNDRV_PCM_STREAM_CAPTURE, true);
+ iccmax_stream = hda_cl_prepare(sdev->dev, HDA_CL_STREAM_FORMAT, PAGE_SIZE,
+ &dmab_bdl, SNDRV_PCM_STREAM_CAPTURE, true);
if (IS_ERR(iccmax_stream)) {
dev_err(sdev->dev, "error: dma prepare for ICCMAX stream failed\n");
return PTR_ERR(iccmax_stream);
@@ -347,7 +351,7 @@ int hda_dsp_cl_boot_firmware_iccmax(struct snd_sof_dev *sdev)
* Perform iccmax stream cleanup. This should be done even if firmware loading fails.
* If the cleanup also fails, we return the initial error
*/
- ret1 = hda_cl_cleanup(sdev, &dmab_bdl, iccmax_stream);
+ ret1 = hda_cl_cleanup(sdev->dev, &dmab_bdl, iccmax_stream);
if (ret1 < 0) {
dev_err(sdev->dev, "error: ICCMAX stream cleanup failed\n");
@@ -419,9 +423,9 @@ int hda_dsp_cl_boot_firmware(struct snd_sof_dev *sdev)
init_waitqueue_head(&sdev->boot_wait);
/* prepare DMA for code loader stream */
- hext_stream = hda_cl_stream_prepare(sdev, HDA_CL_STREAM_FORMAT,
- stripped_firmware.size,
- &dmab, SNDRV_PCM_STREAM_PLAYBACK, false);
+ hext_stream = hda_cl_prepare(sdev->dev, HDA_CL_STREAM_FORMAT,
+ stripped_firmware.size,
+ &dmab, SNDRV_PCM_STREAM_PLAYBACK, false);
if (IS_ERR(hext_stream)) {
dev_err(sdev->dev, "error: dma prepare for fw loading failed\n");
return PTR_ERR(hext_stream);
@@ -494,7 +498,7 @@ int hda_dsp_cl_boot_firmware(struct snd_sof_dev *sdev)
* This should be done even if firmware loading fails.
* If the cleanup also fails, we return the initial error
*/
- ret1 = hda_cl_cleanup(sdev, &dmab, hext_stream);
+ ret1 = hda_cl_cleanup(sdev->dev, &dmab, hext_stream);
if (ret1 < 0) {
dev_err(sdev->dev, "error: Code loader DSP cleanup failed\n");
@@ -536,9 +540,9 @@ int hda_dsp_ipc4_load_library(struct snd_sof_dev *sdev,
stripped_firmware.size = fw_lib->sof_fw.fw->size - fw_lib->sof_fw.payload_offset;
/* prepare DMA for code loader stream */
- hext_stream = hda_cl_stream_prepare(sdev, HDA_CL_STREAM_FORMAT,
- stripped_firmware.size,
- &dmab, SNDRV_PCM_STREAM_PLAYBACK, false);
+ hext_stream = hda_cl_prepare(sdev->dev, HDA_CL_STREAM_FORMAT,
+ stripped_firmware.size,
+ &dmab, SNDRV_PCM_STREAM_PLAYBACK, false);
if (IS_ERR(hext_stream)) {
dev_err(sdev->dev, "%s: DMA prepare failed\n", __func__);
return PTR_ERR(hext_stream);
@@ -581,7 +585,7 @@ int hda_dsp_ipc4_load_library(struct snd_sof_dev *sdev,
goto cleanup;
}
- ret = cl_trigger(sdev, hext_stream, SNDRV_PCM_TRIGGER_START);
+ ret = hda_cl_trigger(sdev->dev, hext_stream, SNDRV_PCM_TRIGGER_START);
if (ret < 0) {
dev_err(sdev->dev, "%s: DMA trigger start failed\n", __func__);
goto cleanup;
@@ -598,7 +602,7 @@ int hda_dsp_ipc4_load_library(struct snd_sof_dev *sdev,
ret = sof_ipc_tx_message_no_reply(sdev->ipc, &msg, 0);
/* Stop the DMA channel */
- ret1 = cl_trigger(sdev, hext_stream, SNDRV_PCM_TRIGGER_STOP);
+ ret1 = hda_cl_trigger(sdev->dev, hext_stream, SNDRV_PCM_TRIGGER_STOP);
if (ret1 < 0) {
dev_err(sdev->dev, "%s: DMA trigger stop failed\n", __func__);
if (!ret)
@@ -607,7 +611,7 @@ int hda_dsp_ipc4_load_library(struct snd_sof_dev *sdev,
cleanup:
/* clean up even in case of error and return the first error */
- ret1 = hda_cl_cleanup(sdev, &dmab, hext_stream);
+ ret1 = hda_cl_cleanup(sdev->dev, &dmab, hext_stream);
if (ret1 < 0) {
dev_err(sdev->dev, "%s: Code loader DSP cleanup failed\n", __func__);
diff --git a/sound/soc/sof/intel/hda.h b/sound/soc/sof/intel/hda.h
index 30a185d4c7ab..b4b037758fcb 100644
--- a/sound/soc/sof/intel/hda.h
+++ b/sound/soc/sof/intel/hda.h
@@ -703,10 +703,13 @@ void hda_dsp_get_state(struct snd_sof_dev *sdev, const char *level);
int hda_dsp_cl_boot_firmware(struct snd_sof_dev *sdev);
int hda_dsp_cl_boot_firmware_iccmax(struct snd_sof_dev *sdev);
int hda_cl_copy_fw(struct snd_sof_dev *sdev, struct hdac_ext_stream *hext_stream);
-struct hdac_ext_stream *hda_cl_stream_prepare(struct snd_sof_dev *sdev, unsigned int format,
- unsigned int size, struct snd_dma_buffer *dmab,
- int direction, bool is_iccmax);
-int hda_cl_cleanup(struct snd_sof_dev *sdev, struct snd_dma_buffer *dmab,
+
+struct hdac_ext_stream *hda_cl_prepare(struct device *dev, unsigned int format,
+ unsigned int size, struct snd_dma_buffer *dmab,
+ int direction, bool is_iccmax);
+int hda_cl_trigger(struct device *dev, struct hdac_ext_stream *hext_stream, int cmd);
+
+int hda_cl_cleanup(struct device *dev, struct snd_dma_buffer *dmab,
struct hdac_ext_stream *hext_stream);
int cl_dsp_init(struct snd_sof_dev *sdev, int stream_tag, bool imr_boot);
#define HDA_CL_STREAM_FORMAT 0x40
--
2.40.1
^ permalink raw reply related [flat|nested] 6+ messages in thread* [PATCH 3/4] ASoC: SOF: Intel: don't ignore IOC interrupts for non-audio transfers
2024-04-04 18:54 [PATCH 0/4] ASoC: SOF: Intel: extend hda-loader for BTP/BRA transfers Pierre-Louis Bossart
2024-04-04 18:54 ` [PATCH 1/4] ASoC: SOF: Intel: hda-loader: add flag to tag ICCMAX stream Pierre-Louis Bossart
2024-04-04 18:54 ` [PATCH 2/4] ASoC: SOF: Intel: hda-loader: change signature of code loader helpers Pierre-Louis Bossart
@ 2024-04-04 18:54 ` Pierre-Louis Bossart
2024-04-04 18:54 ` [PATCH 4/4] ASoC: SOF: Intel: hda-stream: clarify comment Pierre-Louis Bossart
2024-04-05 23:20 ` [PATCH 0/4] ASoC: SOF: Intel: extend hda-loader for BTP/BRA transfers Mark Brown
4 siblings, 0 replies; 6+ messages in thread
From: Pierre-Louis Bossart @ 2024-04-04 18:54 UTC (permalink / raw)
To: linux-sound
Cc: alsa-devel, tiwai, broonie, Pierre-Louis Bossart,
Péter Ujfalusi, Rander Wang, Ranjani Sridharan
The HDaudio stream interrupts are ignored unless the stream is PCM or
compressed audio. For alternate non-audio usages, such as code loader
or SoundWire BPT case, the IOC interrupt on the last buffer
transferred is silently ignored.
This patch adds a 'struct completion' for each HDaudio stream. This
capability helps detect if the non-audio data transfers
completed. There is no performance impact for audio streams.
In the code loader case, the code currently starts the DMA and
directly checks if the firmware status changes, without checking if
the DMA succeeded. With a first pass waiting for the DMA to complete,
system validation engineers can gather more precise timing information
on firmware boot time or root-cause boot failures more accurately.
A timeout of 500ms was selected for the code loader DMA. This is an
experimental value which should be more than enough - higher values
would certainly be problematic from a usage/latency perspective.
Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Reviewed-by: Péter Ujfalusi <peter.ujfalusi@linux.intel.com>
Reviewed-by: Rander Wang <rander.wang@intel.com>
Reviewed-by: Ranjani Sridharan <ranjani.sridharan@linux.intel.com>
---
sound/soc/sof/intel/hda-loader.c | 28 ++++++++++++++++++++++++++++
sound/soc/sof/intel/hda-stream.c | 22 +++++++++++++++++++---
sound/soc/sof/intel/hda.h | 2 ++
3 files changed, 49 insertions(+), 3 deletions(-)
diff --git a/sound/soc/sof/intel/hda-loader.c b/sound/soc/sof/intel/hda-loader.c
index 5716772a7a91..dc88b7ea599e 100644
--- a/sound/soc/sof/intel/hda-loader.c
+++ b/sound/soc/sof/intel/hda-loader.c
@@ -226,10 +226,15 @@ int hda_cl_trigger(struct device *dev, struct hdac_ext_stream *hext_stream, int
struct snd_sof_dev *sdev = dev_get_drvdata(dev);
struct hdac_stream *hstream = &hext_stream->hstream;
int sd_offset = SOF_STREAM_SD_OFFSET(hstream);
+ struct sof_intel_hda_stream *hda_stream;
/* code loader is special case that reuses stream ops */
switch (cmd) {
case SNDRV_PCM_TRIGGER_START:
+ hda_stream = container_of(hext_stream, struct sof_intel_hda_stream,
+ hext_stream);
+ reinit_completion(&hda_stream->ioc);
+
snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, SOF_HDA_INTCTL,
1 << hstream->index,
1 << hstream->index);
@@ -283,19 +288,38 @@ int hda_cl_cleanup(struct device *dev, struct snd_dma_buffer *dmab,
}
EXPORT_SYMBOL_NS(hda_cl_cleanup, SND_SOC_SOF_INTEL_HDA_COMMON);
+#define HDA_CL_DMA_IOC_TIMEOUT_MS 500
+
int hda_cl_copy_fw(struct snd_sof_dev *sdev, struct hdac_ext_stream *hext_stream)
{
struct sof_intel_hda_dev *hda = sdev->pdata->hw_pdata;
const struct sof_intel_dsp_desc *chip = hda->desc;
+ struct sof_intel_hda_stream *hda_stream;
+ unsigned long time_left;
unsigned int reg;
int ret, status;
+ hda_stream = container_of(hext_stream, struct sof_intel_hda_stream,
+ hext_stream);
+
+ dev_dbg(sdev->dev, "Code loader DMA starting\n");
+
ret = hda_cl_trigger(sdev->dev, hext_stream, SNDRV_PCM_TRIGGER_START);
if (ret < 0) {
dev_err(sdev->dev, "error: DMA trigger start failed\n");
return ret;
}
+ /* Wait for completion of transfer */
+ time_left = wait_for_completion_timeout(&hda_stream->ioc,
+ msecs_to_jiffies(HDA_CL_DMA_IOC_TIMEOUT_MS));
+
+ if (!time_left) {
+ dev_err(sdev->dev, "Code loader DMA did not complete\n");
+ return -ETIMEDOUT;
+ }
+ dev_dbg(sdev->dev, "Code loader DMA done, waiting for FW_ENTERED status\n");
+
status = snd_sof_dsp_read_poll_timeout(sdev, HDA_DSP_BAR,
chip->rom_status_reg, reg,
(FSR_TO_STATE_CODE(reg) == FSR_STATE_FW_ENTERED),
@@ -311,6 +335,8 @@ int hda_cl_copy_fw(struct snd_sof_dev *sdev, struct hdac_ext_stream *hext_stream
dev_err(sdev->dev,
"%s: timeout with rom_status_reg (%#x) read\n",
__func__, chip->rom_status_reg);
+ } else {
+ dev_dbg(sdev->dev, "Code loader FW_ENTERED status\n");
}
ret = hda_cl_trigger(sdev->dev, hext_stream, SNDRV_PCM_TRIGGER_STOP);
@@ -318,6 +344,8 @@ int hda_cl_copy_fw(struct snd_sof_dev *sdev, struct hdac_ext_stream *hext_stream
dev_err(sdev->dev, "error: DMA trigger stop failed\n");
if (!status)
status = ret;
+ } else {
+ dev_dbg(sdev->dev, "Code loader DMA stopped\n");
}
return status;
diff --git a/sound/soc/sof/intel/hda-stream.c b/sound/soc/sof/intel/hda-stream.c
index 0c189d3b19c1..76c33795ade4 100644
--- a/sound/soc/sof/intel/hda-stream.c
+++ b/sound/soc/sof/intel/hda-stream.c
@@ -765,10 +765,25 @@ static bool hda_dsp_stream_check(struct hdac_bus *bus, u32 status)
writeb(sd_status, s->sd_addr + SOF_HDA_ADSP_REG_SD_STS);
active = true;
- if ((!s->substream && !s->cstream) ||
- !s->running ||
- (sd_status & SOF_HDA_CL_DMA_SD_INT_COMPLETE) == 0)
+ if (!s->running)
continue;
+ if ((sd_status & SOF_HDA_CL_DMA_SD_INT_COMPLETE) == 0)
+ continue;
+ if (!s->substream && !s->cstream) {
+ /*
+ * when no substream is found, the DMA may used for code loading
+ * or data transfers which can rely on wait_for_completion()
+ */
+ struct sof_intel_hda_stream *hda_stream;
+ struct hdac_ext_stream *hext_stream;
+
+ hext_stream = stream_to_hdac_ext_stream(s);
+ hda_stream = container_of(hext_stream, struct sof_intel_hda_stream,
+ hext_stream);
+
+ complete(&hda_stream->ioc);
+ continue;
+ }
/* Inform ALSA only in case not do that with IPC */
if (s->substream && sof_hda->no_ipc_position) {
@@ -880,6 +895,7 @@ int hda_dsp_stream_init(struct snd_sof_dev *sdev)
return -ENOMEM;
hda_stream->sdev = sdev;
+ init_completion(&hda_stream->ioc);
hext_stream = &hda_stream->hext_stream;
diff --git a/sound/soc/sof/intel/hda.h b/sound/soc/sof/intel/hda.h
index b4b037758fcb..b59d1a572bce 100644
--- a/sound/soc/sof/intel/hda.h
+++ b/sound/soc/sof/intel/hda.h
@@ -11,6 +11,7 @@
#ifndef __SOF_INTEL_HDA_H
#define __SOF_INTEL_HDA_H
+#include <linux/completion.h>
#include <linux/soundwire/sdw.h>
#include <linux/soundwire/sdw_intel.h>
#include <sound/compress_driver.h>
@@ -559,6 +560,7 @@ struct sof_intel_hda_stream {
struct sof_intel_stream sof_intel_stream;
int host_reserved; /* reserve host DMA channel */
u32 flags;
+ struct completion ioc;
};
#define hstream_to_sof_hda_stream(hstream) \
--
2.40.1
^ permalink raw reply related [flat|nested] 6+ messages in thread