diff --git a/drivers/dma/dma_intel_adsp_hda.c b/drivers/dma/dma_intel_adsp_hda.c index abfd085adb52980..2a438ef24a617bc 100644 --- a/drivers/dma/dma_intel_adsp_hda.c +++ b/drivers/dma/dma_intel_adsp_hda.c @@ -454,15 +454,26 @@ void intel_adsp_hda_dma_isr(void) cfg = host_dev[i]->config; for (j = 0; j < dma_ctx->dma_channels; j++) { - if (atomic_test_bit(dma_ctx->atomic, j)) { - clear_l1_exit |= - intel_adsp_hda_check_buffer_interrupt(cfg->base, - cfg->regblock_size, - j); + if (!atomic_test_bit(dma_ctx->atomic, j)) + continue; + + if (!intel_adsp_hda_is_buffer_interrupt_enabled(cfg->base, + cfg->regblock_size, j)) + continue; + + if (intel_adsp_hda_check_buffer_interrupt(cfg->base, + cfg->regblock_size, j)) { + clear_l1_exit = true; intel_adsp_hda_disable_buffer_interrupt(cfg->base, cfg->regblock_size, j); intel_adsp_hda_clear_buffer_interrupt(cfg->base, cfg->regblock_size, j); + } else { + /* + * Postpone entering L1 state until all enabled interrupts + * arrived, i.e. transfer started on all channels. + */ + return; } } } diff --git a/soc/intel/intel_adsp/common/include/intel_adsp_hda.h b/soc/intel/intel_adsp/common/include/intel_adsp_hda.h index 628a84cd1a01df6..47285c03ad5c317 100644 --- a/soc/intel/intel_adsp/common/include/intel_adsp_hda.h +++ b/soc/intel/intel_adsp/common/include/intel_adsp_hda.h @@ -444,6 +444,19 @@ static inline void intel_adsp_hda_disable_buffer_interrupt(uint32_t base, uint32 *DGCS(base, regblock_size, sid) &= ~DGCS_BSCIE; } +/** + * @brief Check if BSC interrupt enabled + * + * @param base Base address of the IP register block + * @param regblock_size Register block size + * @param sid Stream ID + */ +static inline bool intel_adsp_hda_is_buffer_interrupt_enabled(uint32_t base, + uint32_t regblock_size, uint32_t sid) +{ + return (*DGCS(base, regblock_size, sid) & DGCS_BSCIE) == DGCS_BSCIE; +} + static inline void intel_adsp_force_dmi_l0_state(void) { #ifdef CONFIG_SOC_SERIES_INTEL_ADSP_ACE