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>
This commit is contained in:
Laurentiu Mihalcea 2024-03-15 13:31:11 +02:00 committed by Carles Cufí
commit 0ff402657b
3 changed files with 64 additions and 7 deletions

View file

@ -744,7 +744,8 @@ out_enable_dline:
*
* TODO: for now we only support 1 data line per direction.
*/
sai_tx_rx_set_dline_mask(dir, data->regmap, 0x1);
sai_tx_rx_set_dline_mask(dir, data->regmap,
SAI_TX_RX_DLINE_MASK(dir, cfg));
/* this will also enable the async side */
SAI_TX_RX_ENABLE_DISABLE(dir, data->regmap, true);
@ -862,14 +863,25 @@ BUILD_ASSERT(SAI_TX_SYNC_MODE(inst) != SAI_RX_SYNC_MODE(inst) || \
SAI_TX_SYNC_MODE(inst) != kSAI_ModeSync, \
"transmitter and receiver can't be both SYNC with each other"); \
\
BUILD_ASSERT(SAI_DLINE_COUNT(inst) != -1, \
"bad or unsupported SAI instance. Is the base address correct?"); \
\
BUILD_ASSERT(SAI_TX_DLINE_INDEX(inst) >= 0 && \
(SAI_TX_DLINE_INDEX(inst) < SAI_DLINE_COUNT(inst)), \
"invalid TX data line index"); \
\
BUILD_ASSERT(SAI_RX_DLINE_INDEX(inst) >= 0 && \
(SAI_RX_DLINE_INDEX(inst) < SAI_DLINE_COUNT(inst)), \
"invalid RX data line index"); \
\
static const struct dai_properties sai_tx_props_##inst = { \
.fifo_address = SAI_TX_FIFO_BASE(inst), \
.fifo_address = SAI_TX_FIFO_BASE(inst, SAI_TX_DLINE_INDEX(inst)), \
.fifo_depth = SAI_FIFO_DEPTH(inst) * CONFIG_SAI_FIFO_WORD_SIZE, \
.dma_hs_id = SAI_TX_RX_DMA_HANDSHAKE(inst, tx), \
}; \
\
static const struct dai_properties sai_rx_props_##inst = { \
.fifo_address = SAI_RX_FIFO_BASE(inst), \
.fifo_address = SAI_RX_FIFO_BASE(inst, SAI_RX_DLINE_INDEX(inst)), \
.fifo_depth = SAI_FIFO_DEPTH(inst) * CONFIG_SAI_FIFO_WORD_SIZE, \
.dma_hs_id = SAI_TX_RX_DMA_HANDSHAKE(inst, rx), \
}; \
@ -896,6 +908,8 @@ static struct sai_config sai_config_##inst = { \
.irq_config = irq_config_##inst, \
.tx_sync_mode = SAI_TX_SYNC_MODE(inst), \
.rx_sync_mode = SAI_RX_SYNC_MODE(inst), \
.tx_dline = SAI_TX_DLINE_INDEX(inst), \
.rx_dline = SAI_RX_DLINE_INDEX(inst), \
}; \
\
static struct sai_data sai_data_##inst = { \

View file

@ -102,12 +102,12 @@ LOG_MODULE_REGISTER(nxp_dai_sai);
FSL_FEATURE_SAI_FIFO_COUNTn(UINT_TO_I2S(DT_INST_REG_ADDR(inst))) / 2)
/* used to retrieve TDR0's address based on SAI's physical address */
#define SAI_TX_FIFO_BASE(inst)\
POINTER_TO_UINT(&(UINT_TO_I2S(DT_INST_REG_ADDR(inst))->TDR[0]))
#define SAI_TX_FIFO_BASE(inst, idx)\
POINTER_TO_UINT(&(UINT_TO_I2S(DT_INST_REG_ADDR(inst))->TDR[idx]))
/* used to retrieve RDR0's address based on SAI's physical address */
#define SAI_RX_FIFO_BASE(inst)\
POINTER_TO_UINT(&(UINT_TO_I2S(DT_INST_REG_ADDR(inst))->RDR[0]))
#define SAI_RX_FIFO_BASE(inst, idx)\
POINTER_TO_UINT(&(UINT_TO_I2S(DT_INST_REG_ADDR(inst))->RDR[idx]))
/* internal macro used to retrieve the default TX/RX FIFO's size (in FIFO words) */
#define _SAI_FIFO_DEPTH(inst)\
@ -146,6 +146,16 @@ LOG_MODULE_REGISTER(nxp_dai_sai);
((DT_INST_DMAS_CELL_BY_NAME(inst, dir, channel) & GENMASK(7, 0)) |\
((DT_INST_DMAS_CELL_BY_NAME(inst, dir, mux) << 8) & GENMASK(15, 8)))
/* used to retrieve the number of supported transmission/receive lines */
#define SAI_DLINE_COUNT(inst)\
FSL_FEATURE_SAI_CHANNEL_COUNTn(UINT_TO_I2S(DT_INST_REG_ADDR(inst)))
/* used to retrieve the index of the transmission line */
#define SAI_TX_DLINE_INDEX(inst) DT_INST_PROP_OR(inst, tx_dataline, 0)
/* used to retrieve the index of the receive line */
#define SAI_RX_DLINE_INDEX(inst) DT_INST_PROP_OR(inst, rx_dataline, 0)
/* utility macros */
/* invert a clock's polarity. This works because a clock's polarity is expressed
@ -215,6 +225,12 @@ LOG_MODULE_REGISTER(nxp_dai_sai);
#define SAI_TX_RX_DIR_IS_SW_ENABLED(dir, data)\
((dir) == DAI_DIR_TX ? data->tx_enabled : data->rx_enabled)
/* used to compute the mask for the transmission/receive lines based on
* the index passed from the DTS.
*/
#define SAI_TX_RX_DLINE_MASK(dir, cfg)\
((dir) == DAI_DIR_TX ? BIT((cfg)->tx_dline) : BIT((cfg)->rx_dline))
struct sai_clock_data {
uint32_t *clocks;
uint32_t clock_num;
@ -253,6 +269,8 @@ struct sai_config {
/* TX synchronization mode - may be SYNC or ASYNC */
sai_sync_mode_t tx_sync_mode;
void (*irq_config)(void);
uint32_t tx_dline;
uint32_t rx_dline;
};
/* this needs to perfectly match SOF's struct sof_ipc_dai_sai_params */

View file

@ -84,3 +84,28 @@ properties:
If this property is not specified, the receiver will be set to ASYNC.
If one side is SYNC then the other MUST be ASYNC. Failing to meet this
condition will result in a failed BUILD_ASSERT().
tx-dataline:
type: int
description: |
Use this property to specify which transmission data line the SAI should
use. To find out which transmission line you should use you can:
1) Check the TRM and see if your SAI instance is multiline. If not then
you're going to use transmission line 0.
2) If your SAI is multiline then you need to check the datasheet and see
the index of the transmission line that's connected to your consumer
(e.g: the codec).
The indexing of the data line starts at 0. If this property is not specified
then the index of the transmission data line will be 0.
Please note that "channel" and "data line" are synnonyms in this context.
rx-dataline:
type: int
description: |
Use this property to specify which receive transmission data line the SAI should
use. To find out which receive line you should use you can:
1) Check the TRM and see if your SAI instance is multiline. If not then
you're going to use receive line 0.
2) If your SAI is multiline then you need to check the datasheet and see
the index of the receive line that's connected to your consumer (e.g: the codec).
The indexing of the data line starts at 0. If this property is not specified
then the index of the receive data line will be 0.
Please note that "channel" and "data line" are synnonyms in this context.