We are developing a system using an i.MX 8M Mini connected to an external audio codec (controlled via I2C) through SAI (I2S), running a kernel with the PREEMPT_RT configuration. We need to perform codec operations (I2C) before the I2S BCLK stops. Where would be the best place to insert this I2C handling?
Best place: put the “must happen before BCLK stops” operation in the ASoC stop path before the fsl-sai CPU DAI trigger(STOP) runs — preferably as a codec/component stop-trigger callback, or as a machine-driver link/component trigger callback ordered before the CPU DAI stop.
Why: on i.MX 8M Mini the NXP fsl_sai_trigger() handles SNDRV_PCM_TRIGGER_STOP by disabling FIFO DMA request/interrupts and then calling fsl_sai_config_disable() , which clears FSL_SAI_CSR_TERE and waits until the current frame completes; in master mode it then resets the SAI block. That is the point where the SAI-generated BCLK is being stopped/disabled. The i.MX8MM SAI driver is registered with .trigger = fsl_sai_trigger and .hw_free = fsl_sai_hw_free in its DAI ops, so hw_free() is already too late for a “before BCLK stops” requirement.
I would avoid adding codec I2C directly inside fsl_sai_trigger() unless this is a board-specific BSP hack. It couples a generic CPU-DAI driver to one codec/board policy. The Linux/NXP ASoC split is intended to keep codec control I/O in the codec driver and CPU interface control in the platform/CPU DAI driver; NXP documentation describes codec control I/O over I2C as codec-driver functionality exported through ASoC DAI ops.
Two practical implementation patterns:
Important PREEMPT_RT note: normal I2C transfers are task-context operations; kernel I2C documentation says I2C protocol operations are usable only from task context, with separate optional atomic transfer hooks for special late-shutdown cases. Therefore, do not perform blocking I2C from an atomic PCM trigger path unless your PCM/ASoC path is configured as non-atomic and you have verified the callback context in your kernel. If the trigger path is atomic, use a safer architecture: prepare the codec state earlier, keep BCLK continuous/gated later, or move the operation to a sleepable ordered stop path rather than doing raw I2C in the CPU DAI trigger.