From e4c7f4d62aec287b7bebb9a0ac5f206002ecd0eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20G=C5=82=C4=85bek?= Date: Tue, 13 Apr 2021 08:55:35 +0200 Subject: [PATCH] drivers: i2s: Introduce the I2S_DIR_BOTH enumeration value MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Introduce a new enumeration value that allows setting configuration and triggering commands for both I2S streams simultaneously. Such possibility is especially important on hardware where the streams can be only enabled/disabled (but not started/stopped) independently, like it is in nRF SoCs. Signed-off-by: Andrzej Głąbek --- drivers/i2s/i2s_cavs.c | 4 ++++ drivers/i2s/i2s_litex.c | 4 ++++ drivers/i2s/i2s_ll_stm32.c | 4 ++++ drivers/i2s/i2s_mcux_flexcomm.c | 4 ++++ drivers/i2s/i2s_sam_ssc.c | 4 ++++ include/drivers/i2s.h | 13 +++++++++++-- 6 files changed, 31 insertions(+), 2 deletions(-) diff --git a/drivers/i2s/i2s_cavs.c b/drivers/i2s/i2s_cavs.c index aaabfd4660..50fcebb1d6 100644 --- a/drivers/i2s/i2s_cavs.c +++ b/drivers/i2s/i2s_cavs.c @@ -642,6 +642,10 @@ static int i2s_cavs_trigger(const struct device *dev, enum i2s_dir dir, unsigned int key; int ret = 0; + if (dir == I2S_DIR_BOTH) { + return -ENOSYS; + } + strm = (dir == I2S_DIR_TX) ? &dev_data->tx : &dev_data->rx; key = irq_lock(); diff --git a/drivers/i2s/i2s_litex.c b/drivers/i2s/i2s_litex.c index 1879c6ee9a..ec159c7a81 100644 --- a/drivers/i2s/i2s_litex.c +++ b/drivers/i2s/i2s_litex.c @@ -351,6 +351,8 @@ static int i2s_litex_configure(const struct device *dev, enum i2s_dir dir, stream = &dev_data->tx; channels_concatenated = litex_read8(I2S_TX_STATUS_REG) & I2S_TX_STAT_CHANNEL_CONCATENATED_MASK; + } else if (dir == I2S_DIR_BOTH) { + return -ENOSYS; } else { LOG_ERR("either RX or TX direction must be selected"); return -EINVAL; @@ -498,6 +500,8 @@ static int i2s_litex_trigger(const struct device *dev, enum i2s_dir dir, stream = &dev_data->rx; } else if (dir == I2S_DIR_TX) { stream = &dev_data->tx; + } else if (dir == I2S_DIR_BOTH) { + return -ENOSYS; } else { LOG_ERR("either RX or TX direction must be selected"); return -EINVAL; diff --git a/drivers/i2s/i2s_ll_stm32.c b/drivers/i2s/i2s_ll_stm32.c index fbff0b788c..ebc5df4d22 100644 --- a/drivers/i2s/i2s_ll_stm32.c +++ b/drivers/i2s/i2s_ll_stm32.c @@ -193,6 +193,8 @@ static int i2s_stm32_configure(const struct device *dev, enum i2s_dir dir, stream = &dev_data->rx; } else if (dir == I2S_DIR_TX) { stream = &dev_data->tx; + } else if (dir == I2S_DIR_BOTH) { + return -ENOSYS; } else { LOG_ERR("Either RX or TX direction must be selected"); return -EINVAL; @@ -296,6 +298,8 @@ static int i2s_stm32_trigger(const struct device *dev, enum i2s_dir dir, stream = &dev_data->rx; } else if (dir == I2S_DIR_TX) { stream = &dev_data->tx; + } else if (dir == I2S_DIR_BOTH) { + return -ENOSYS; } else { LOG_ERR("Either RX or TX direction must be selected"); return -EINVAL; diff --git a/drivers/i2s/i2s_mcux_flexcomm.c b/drivers/i2s/i2s_mcux_flexcomm.c index 4c2c8764dd..c67d28303c 100644 --- a/drivers/i2s/i2s_mcux_flexcomm.c +++ b/drivers/i2s/i2s_mcux_flexcomm.c @@ -185,6 +185,8 @@ static int i2s_mcux_configure(const struct device *dev, enum i2s_dir dir, stream = &dev_data->rx; } else if (dir == I2S_DIR_TX) { stream = &dev_data->tx; + } else if (dir == I2S_DIR_BOTH) { + return -ENOSYS; } else { LOG_ERR("Either RX or TX direction must be selected"); return -EINVAL; @@ -643,6 +645,8 @@ static int i2s_mcux_trigger(const struct device *dev, enum i2s_dir dir, stream = &dev_data->rx; } else if (dir == I2S_DIR_TX) { stream = &dev_data->tx; + } else if (dir == I2S_DIR_BOTH) { + return -ENOSYS; } else { LOG_ERR("Either RX or TX direction must be selected"); return -EINVAL; diff --git a/drivers/i2s/i2s_sam_ssc.c b/drivers/i2s/i2s_sam_ssc.c index 640d920c6a..be7201fee1 100644 --- a/drivers/i2s/i2s_sam_ssc.c +++ b/drivers/i2s/i2s_sam_ssc.c @@ -551,6 +551,8 @@ static int i2s_sam_configure(const struct device *dev, enum i2s_dir dir, stream = &dev_data->rx; } else if (dir == I2S_DIR_TX) { stream = &dev_data->tx; + } else if (dir == I2S_DIR_BOTH) { + return -ENOSYS; } else { LOG_ERR("Either RX or TX direction must be selected"); return -EINVAL; @@ -763,6 +765,8 @@ static int i2s_sam_trigger(const struct device *dev, enum i2s_dir dir, stream = &dev_data->rx; } else if (dir == I2S_DIR_TX) { stream = &dev_data->tx; + } else if (dir == I2S_DIR_BOTH) { + return -ENOSYS; } else { LOG_ERR("Either RX or TX direction must be selected"); return -EINVAL; diff --git a/include/drivers/i2s.h b/include/drivers/i2s.h index 164587d1eb..b96be3efb5 100644 --- a/include/drivers/i2s.h +++ b/include/drivers/i2s.h @@ -207,6 +207,8 @@ enum i2s_dir { I2S_DIR_RX, /** Transmit data */ I2S_DIR_TX, + /** Both receive and transmit data */ + I2S_DIR_BOTH, }; /** Interface state */ @@ -339,11 +341,14 @@ __subsystem struct i2s_driver_api { * the interface state will be changed to NOT_READY. * * @param dev Pointer to the device structure for the driver instance. - * @param dir Stream direction: RX or TX as defined by I2S_DIR_* + * @param dir Stream direction: RX, TX, or both, as defined by I2S_DIR_*. + * The I2S_DIR_BOTH value may not be supported by some drivers. + * For those, the RX and TX streams need to be configured separately. * @param cfg Pointer to the structure containing configuration parameters. * * @retval 0 If successful. * @retval -EINVAL Invalid argument. + * @retval -ENOSYS I2S_DIR_BOTH value is not supported. */ __syscall int i2s_configure(const struct device *dev, enum i2s_dir dir, struct i2s_config *cfg); @@ -501,7 +506,10 @@ __syscall int i2s_buf_write(const struct device *dev, void *buf, size_t size); * @brief Send a trigger command. * * @param dev Pointer to the device structure for the driver instance. - * @param dir Stream direction: RX or TX. + * @param dir Stream direction: RX, TX, or both, as defined by I2S_DIR_*. + * The I2S_DIR_BOTH value may not be supported by some drivers. + * For those, triggering need to be done separately for the RX + * and TX streams. * @param cmd Trigger command. * * @retval 0 If successful. @@ -509,6 +517,7 @@ __syscall int i2s_buf_write(const struct device *dev, void *buf, size_t size); * @retval -EIO The trigger cannot be executed in the current state or a DMA * channel cannot be allocated. * @retval -ENOMEM RX/TX memory block not available. + * @retval -ENOSYS I2S_DIR_BOTH value is not supported. */ __syscall int i2s_trigger(const struct device *dev, enum i2s_dir dir, enum i2s_trigger_cmd cmd);