Skip to content

Commit ae08206

Browse files
LaurentiuM1234carlescufi
authored andcommitted
drivers: dai: sai: write some data into TX FIFO before start
While running the following command: aplay ... | arecord ... multiple times, it was discovered that the SAI transmit FIFO goes into underrun. This only happened in the beginning, a few BCLK cycles after unmasking the transmit data line. With the following flow: 1) Trigger start on RX a) Do TX and RX software reset b) Enable RX FIFO error interrupt c) Enable RX DMA requests d) Enable receive data line e) Enable transmitter f) Enable receiver ..... some time has passed ..... 2) Trigger start on TX a) Enable DMA requests b) Enable transmit data line and configuration in mind: 1) RX is SYNC with TX 2) TX is ASYNC 3) Each FSYNC edge is 32-bit wide 4) Each frame contains 2 32-bit words this points to the following possibilites: 1) The transmitter is enabled so close to the start of a new frame that even though the DMA requests are asserted, the DMAC doesn't have enough time to service them until the module goes into underrun => the timing is bad. 2) The transmitter is enabled somewhat close to the start of a new frame such that the DMAC is not fast enough to service the module until it goes into underrun => DMAC is too slow AND the timing is bad. Although the exact cause was not pinpointed, this patch aims to fix the problem by writing a frame's worth of 0s in the transmit FIFO. This way, even if we're dealing with scenario 1) or 2), the DMAC has plenty of time to perform the transfer (i.e: a frame), thus avoiding the underrun. Signed-off-by: Laurentiu Mihalcea <laurentiu.mihalcea@nxp.com>
1 parent b039442 commit ae08206

File tree

1 file changed

+7
-2
lines changed

1 file changed

+7
-2
lines changed

drivers/dai/nxp/sai/sai.c

+7-2
Original file line numberDiff line numberDiff line change
@@ -696,7 +696,7 @@ static int sai_trigger_start(const struct device *dev,
696696
struct sai_data *data;
697697
const struct sai_config *cfg;
698698
uint32_t old_state;
699-
int ret;
699+
int ret, i;
700700

701701
data = dev->data;
702702
cfg = dev->config;
@@ -733,7 +733,12 @@ static int sai_trigger_start(const struct device *dev,
733733
SAI_TX_RX_ENABLE_DISABLE_IRQ(dir, data->regmap,
734734
kSAI_FIFOErrorInterruptEnable, true);
735735

736-
/* TODO: is there a need to write some words to the FIFO to avoid starvation? */
736+
/* avoid initial underrun by writing a frame's worth of 0s */
737+
if (dir == DAI_DIR_TX) {
738+
for (i = 0; i < data->cfg.channels; i++) {
739+
SAI_WriteData(UINT_TO_I2S(data->regmap), cfg->tx_dline, 0x0);
740+
}
741+
}
737742

738743
/* TODO: for now, only DMA mode is supported */
739744
SAI_TX_RX_DMA_ENABLE_DISABLE(dir, data->regmap, true);

0 commit comments

Comments
 (0)