dai: nxp: sai: Disable data line on pause trigger

Currently, whenever performing TRIGGER_PAUSE operation, the
data line is not disabled. This works well if TX and RX don't
operate at the same time or they operate in ASYNC-ASYNC mode. This
is because sai_tx_rx_disable() will disable transmitter/receiver
all the time since there's no dependencies to take into consideration.
However, in the ASYNC-SYNC mode, sai_tx_rx_disable() may not disable
the current asynchronous side if the synchronous side is still enabled.
As a consequence, the asynchronous side will remain enabled, thus
leading to an underrun/overrun.

To fix this issue, sai_trigger_pause() should disable the data line
each time it's called. This way, even if sai_tx_rx_disable() doesn't
disable the current direction, the data line will be disabled, thus
stopping the consumption/production of frames.

Signed-off-by: Laurentiu Mihalcea <laurentiu.mihalcea@nxp.com>
This commit is contained in:
Laurentiu Mihalcea 2024-01-22 13:14:46 +02:00 committed by Maureen Helm
commit 6644fa9104

View file

@ -563,6 +563,9 @@ static int sai_trigger_pause(const struct device *dev,
return ret;
}
/* disable TX/RX data line */
sai_tx_rx_set_dline_mask(dir, data->regmap, 0x0);
/* update the software state of TX/RX */
sai_tx_rx_sw_enable_disable(dir, data, false);
@ -601,7 +604,7 @@ static int sai_trigger_stop(const struct device *dev,
* left to do is disable the DMA requests and
* the data line.
*/
goto out_dline_disable;
goto out_dmareq_disable;
}
ret = sai_tx_rx_disable(data, cfg, dir);
@ -612,10 +615,10 @@ static int sai_trigger_stop(const struct device *dev,
/* update the software state of TX/RX */
sai_tx_rx_sw_enable_disable(dir, data, false);
out_dline_disable:
/* disable TX/RX data line */
sai_tx_rx_set_dline_mask(dir, data->regmap, 0x0);
out_dmareq_disable:
/* disable DMA requests */
SAI_TX_RX_DMA_ENABLE_DISABLE(dir, data->regmap, false);
@ -719,7 +722,7 @@ static int sai_trigger_start(const struct device *dev,
* skip this part and go directly to the TX/RX
* enablement.
*/
goto out_enable_tx_rx;
goto out_enable_dline;
}
LOG_DBG("start on direction %d", dir);
@ -735,6 +738,7 @@ static int sai_trigger_start(const struct device *dev,
/* TODO: for now, only DMA mode is supported */
SAI_TX_RX_DMA_ENABLE_DISABLE(dir, data->regmap, true);
out_enable_dline:
/* enable TX/RX data line. This translates to TX_DLINE0/RX_DLINE0
* being enabled.
*
@ -742,7 +746,6 @@ static int sai_trigger_start(const struct device *dev,
*/
sai_tx_rx_set_dline_mask(dir, data->regmap, 0x1);
out_enable_tx_rx:
/* this will also enable the async side */
SAI_TX_RX_ENABLE_DISABLE(dir, data->regmap, true);