Commit graph

11 commits

Author SHA1 Message Date
Laurentiu Mihalcea
e224a41ec8 drivers: dai: sai: don't crash on underrun/overrun
TX/RX FIFO underrun shouldn't crash the RTOS when it occurs.
Also, since this can also happen under "normal" conditions
(i.e: DMA doesn't copy data fast enough from/to SAI's FIFOs)
the software should be able to recover from it.

As such:
	1) Remove `z_irq_spurious()` call.
	2) Clear error flag
	3) De-escalate error message to warning message

Signed-off-by: Laurentiu Mihalcea <laurentiu.mihalcea@nxp.com>
2024-08-27 10:50:53 -04:00
Laurentiu Mihalcea
ae082064ff 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>
2024-05-17 12:40:43 +02:00
Laurentiu Mihalcea
f4c73105e5 drivers: dai: sai: add pinctrl support
Add support for performing pinctrl operations. For now,
the only supported operation is applying the pinctrl default
state. Pinctrl is left optional to allow for scenarios in which
this is not required (e.g: AMP system in which another
OS configures the pinctrl).

Signed-off-by: Laurentiu Mihalcea <laurentiu.mihalcea@nxp.com>
2024-04-02 14:31:15 +01:00
Laurentiu Mihalcea
0ff402657b nxp: sai: add support for passing TX/RX data line through DTS
Some SAI instances are mutliline, meaning they can have multiple
TX/RX data lines (channels). Depending on the board, the index
of the TX/RX data lines that are connected to the consumer
(e.g: the codec) may not always be 0. This commit fixes this
issue by adding support for passing the index of the used
TX/RX data lines through the DTS.

Signed-off-by: Laurentiu Mihalcea <laurentiu.mihalcea@nxp.com>
2024-03-19 14:30:32 +01:00
Laurentiu Mihalcea
b803e06099 drivers: dai: sai: use "dmas" property for handshake encoding
Since a DMA cell now allows specifying a channel and a MUX value
there's no need to fetch these values from the HAL. This, in turn,
allows for more flexibility and reduces the coding effort for new
platforms that want to use the SAI driver.

Signed-off-by: Laurentiu Mihalcea <laurentiu.mihalcea@nxp.com>
2024-03-08 09:38:25 +01:00
Laurentiu Mihalcea
6644fa9104 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>
2024-02-01 14:27:37 -06:00
Roman Studenikin
260fc89643 drivers: use DT_INST_PROP over DT_INST_PROP_OR if possible
It might happens that DT(_INST)_PROP_OR is used with boolean properties.
For instance:

	.single_wire = DT_INST_PROP_OR(index, single_wire, false),	\
	.tx_rx_swap = DT_INST_PROP_OR(index, tx_rx_swap, false),	\

This is not required as boolean properties are generated with false
value when not present, so the _OR macro extension is superflous
and the above code can be replaced by:

	.single_wire = DT_INST_PROP(index, single_wire),		\
	.tx_rx_swap = DT_INST_PROP(index, tx_rx_swap),			\

Signed-off-by: Roman Studenikin <srv@meta.com>
2024-01-30 00:26:58 +00:00
Laurentiu Mihalcea
265554b873 drivers: dai: sai: Add fix for i.MX93 SAI errata 051421
ERRATA 051421 states that if the SAI is FSYNC/BCLK master,
one of the directions is SYNC with the other, and the
ASYNC direction has the BYP bit toggled, the SYNC direction's
BCLK won't be generated properly.

This commit fixes this issue by enabling BCI for the SYNC
direction. What this does is it makes the SYNC direction use
the BCLK from the ASYNC direction's pad, which, if the BYP
bit is toggled, will be the undivided MCLK. Without this fix,
the SYNC direction will use the ASYNC direction's BCLK obtained
by dividing the MCLK via the following formula: MCLK / ((DIV + 1) * 2).
This is wrong because the ASYNC direction will use an undivided
MCLK while the SYNC direction will use a divided MCLK.

Signed-off-by: Laurentiu Mihalcea <laurentiu.mihalcea@nxp.com>
2024-01-11 10:02:50 +01:00
Laurentiu Mihalcea
0db2d17b48 drivers: dai: sai: Add support for all SYNC modes
With the introduction of the "rx_sync_mode" and "tx_sync_mode"
properties, the user may choose which synchronization mode the
SAI should use. To support this, the code had to be changed a
bit such that the software reset and the disable operations
work on all synchronization modes.

What this commit does, is it changes the software reset and
disable sequences such that they work with any of the
supported synchronization modes. Also, the syncMode field
of sai_transceiver_t structure is set to the value passed
from the DTS during sai_config_set().

Signed-off-by: Laurentiu Mihalcea <laurentiu.mihalcea@nxp.com>
2024-01-11 10:02:50 +01:00
Laurentiu Mihalcea
6127535b1d drivers: dai: sai: Introduce the rx_sync_mode/tx_sync_mode properties
In preparation for supporting all synchronization modes, this
commit introduces the rx_sync_mode/tx_sync_mode DTS properties.
Using these, the user will be able to specify which synchronization
mode the SAI should use.

At the moment, the driver does nothing with the values from
said properties but still checks if their values are sane
(i.e: it checks if the directions are both in SYNC mode which
is forbidden). By default, if "rx_sync_mode" or "tx_sync_mode"
is not specified, the direction will be set to ASYNC mode.
As such, below one may find a couple of valid examples
depicting this idea:

	tx_sync_mode = <0>;
	rx_sync_mode = <0>;

is the same as not specifying any of the properties,

	tx_sync_mode = <1>;
	rx_sync_mode = <0>;

is the same as:

	tx_sync_mode = <1>;

Signed-off-by: Laurentiu Mihalcea <laurentiu.mihalcea@nxp.com>
2024-01-11 10:02:50 +01:00
Laurentiu Mihalcea
fe64d840cc drivers: dai: Add driver for NXP's SAI
This commit introduces a new DAI driver used for NXP'S SAI IP.

Signed-off-by: Laurentiu Mihalcea <laurentiu.mihalcea@nxp.com>
2023-12-20 11:15:13 +01:00