From 0ff402657b3012d6cfdd06096cd83fa3457dcb37 Mon Sep 17 00:00:00 2001 From: Laurentiu Mihalcea Date: Fri, 15 Mar 2024 13:31:11 +0200 Subject: [PATCH] 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 --- drivers/dai/nxp/sai/sai.c | 20 +++++++++++++++++--- drivers/dai/nxp/sai/sai.h | 26 ++++++++++++++++++++++---- dts/bindings/dai/nxp,dai-sai.yaml | 25 +++++++++++++++++++++++++ 3 files changed, 64 insertions(+), 7 deletions(-) diff --git a/drivers/dai/nxp/sai/sai.c b/drivers/dai/nxp/sai/sai.c index fd279fef2fd..9af53287eb5 100644 --- a/drivers/dai/nxp/sai/sai.c +++ b/drivers/dai/nxp/sai/sai.c @@ -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 = { \ diff --git a/drivers/dai/nxp/sai/sai.h b/drivers/dai/nxp/sai/sai.h index b5e07b45395..10296717e83 100644 --- a/drivers/dai/nxp/sai/sai.h +++ b/drivers/dai/nxp/sai/sai.h @@ -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 */ diff --git a/dts/bindings/dai/nxp,dai-sai.yaml b/dts/bindings/dai/nxp,dai-sai.yaml index ae9cd201880..ec2bc88c392 100644 --- a/dts/bindings/dai/nxp,dai-sai.yaml +++ b/dts/bindings/dai/nxp,dai-sai.yaml @@ -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.