drivers: i2s: Introduce the I2S_DIR_BOTH enumeration value

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 <andrzej.glabek@nordicsemi.no>
This commit is contained in:
Andrzej Głąbek 2021-04-13 08:55:35 +02:00 committed by Anas Nashif
commit e4c7f4d62a
6 changed files with 31 additions and 2 deletions

View file

@ -642,6 +642,10 @@ static int i2s_cavs_trigger(const struct device *dev, enum i2s_dir dir,
unsigned int key; unsigned int key;
int ret = 0; int ret = 0;
if (dir == I2S_DIR_BOTH) {
return -ENOSYS;
}
strm = (dir == I2S_DIR_TX) ? &dev_data->tx : &dev_data->rx; strm = (dir == I2S_DIR_TX) ? &dev_data->tx : &dev_data->rx;
key = irq_lock(); key = irq_lock();

View file

@ -351,6 +351,8 @@ static int i2s_litex_configure(const struct device *dev, enum i2s_dir dir,
stream = &dev_data->tx; stream = &dev_data->tx;
channels_concatenated = litex_read8(I2S_TX_STATUS_REG) & channels_concatenated = litex_read8(I2S_TX_STATUS_REG) &
I2S_TX_STAT_CHANNEL_CONCATENATED_MASK; I2S_TX_STAT_CHANNEL_CONCATENATED_MASK;
} else if (dir == I2S_DIR_BOTH) {
return -ENOSYS;
} else { } else {
LOG_ERR("either RX or TX direction must be selected"); LOG_ERR("either RX or TX direction must be selected");
return -EINVAL; return -EINVAL;
@ -498,6 +500,8 @@ static int i2s_litex_trigger(const struct device *dev, enum i2s_dir dir,
stream = &dev_data->rx; stream = &dev_data->rx;
} else if (dir == I2S_DIR_TX) { } else if (dir == I2S_DIR_TX) {
stream = &dev_data->tx; stream = &dev_data->tx;
} else if (dir == I2S_DIR_BOTH) {
return -ENOSYS;
} else { } else {
LOG_ERR("either RX or TX direction must be selected"); LOG_ERR("either RX or TX direction must be selected");
return -EINVAL; return -EINVAL;

View file

@ -193,6 +193,8 @@ static int i2s_stm32_configure(const struct device *dev, enum i2s_dir dir,
stream = &dev_data->rx; stream = &dev_data->rx;
} else if (dir == I2S_DIR_TX) { } else if (dir == I2S_DIR_TX) {
stream = &dev_data->tx; stream = &dev_data->tx;
} else if (dir == I2S_DIR_BOTH) {
return -ENOSYS;
} else { } else {
LOG_ERR("Either RX or TX direction must be selected"); LOG_ERR("Either RX or TX direction must be selected");
return -EINVAL; return -EINVAL;
@ -296,6 +298,8 @@ static int i2s_stm32_trigger(const struct device *dev, enum i2s_dir dir,
stream = &dev_data->rx; stream = &dev_data->rx;
} else if (dir == I2S_DIR_TX) { } else if (dir == I2S_DIR_TX) {
stream = &dev_data->tx; stream = &dev_data->tx;
} else if (dir == I2S_DIR_BOTH) {
return -ENOSYS;
} else { } else {
LOG_ERR("Either RX or TX direction must be selected"); LOG_ERR("Either RX or TX direction must be selected");
return -EINVAL; return -EINVAL;

View file

@ -185,6 +185,8 @@ static int i2s_mcux_configure(const struct device *dev, enum i2s_dir dir,
stream = &dev_data->rx; stream = &dev_data->rx;
} else if (dir == I2S_DIR_TX) { } else if (dir == I2S_DIR_TX) {
stream = &dev_data->tx; stream = &dev_data->tx;
} else if (dir == I2S_DIR_BOTH) {
return -ENOSYS;
} else { } else {
LOG_ERR("Either RX or TX direction must be selected"); LOG_ERR("Either RX or TX direction must be selected");
return -EINVAL; return -EINVAL;
@ -643,6 +645,8 @@ static int i2s_mcux_trigger(const struct device *dev, enum i2s_dir dir,
stream = &dev_data->rx; stream = &dev_data->rx;
} else if (dir == I2S_DIR_TX) { } else if (dir == I2S_DIR_TX) {
stream = &dev_data->tx; stream = &dev_data->tx;
} else if (dir == I2S_DIR_BOTH) {
return -ENOSYS;
} else { } else {
LOG_ERR("Either RX or TX direction must be selected"); LOG_ERR("Either RX or TX direction must be selected");
return -EINVAL; return -EINVAL;

View file

@ -551,6 +551,8 @@ static int i2s_sam_configure(const struct device *dev, enum i2s_dir dir,
stream = &dev_data->rx; stream = &dev_data->rx;
} else if (dir == I2S_DIR_TX) { } else if (dir == I2S_DIR_TX) {
stream = &dev_data->tx; stream = &dev_data->tx;
} else if (dir == I2S_DIR_BOTH) {
return -ENOSYS;
} else { } else {
LOG_ERR("Either RX or TX direction must be selected"); LOG_ERR("Either RX or TX direction must be selected");
return -EINVAL; return -EINVAL;
@ -763,6 +765,8 @@ static int i2s_sam_trigger(const struct device *dev, enum i2s_dir dir,
stream = &dev_data->rx; stream = &dev_data->rx;
} else if (dir == I2S_DIR_TX) { } else if (dir == I2S_DIR_TX) {
stream = &dev_data->tx; stream = &dev_data->tx;
} else if (dir == I2S_DIR_BOTH) {
return -ENOSYS;
} else { } else {
LOG_ERR("Either RX or TX direction must be selected"); LOG_ERR("Either RX or TX direction must be selected");
return -EINVAL; return -EINVAL;

View file

@ -207,6 +207,8 @@ enum i2s_dir {
I2S_DIR_RX, I2S_DIR_RX,
/** Transmit data */ /** Transmit data */
I2S_DIR_TX, I2S_DIR_TX,
/** Both receive and transmit data */
I2S_DIR_BOTH,
}; };
/** Interface state */ /** Interface state */
@ -339,11 +341,14 @@ __subsystem struct i2s_driver_api {
* the interface state will be changed to NOT_READY. * the interface state will be changed to NOT_READY.
* *
* @param dev Pointer to the device structure for the driver instance. * @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. * @param cfg Pointer to the structure containing configuration parameters.
* *
* @retval 0 If successful. * @retval 0 If successful.
* @retval -EINVAL Invalid argument. * @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, __syscall int i2s_configure(const struct device *dev, enum i2s_dir dir,
struct i2s_config *cfg); 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. * @brief Send a trigger command.
* *
* @param dev Pointer to the device structure for the driver instance. * @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. * @param cmd Trigger command.
* *
* @retval 0 If successful. * @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 * @retval -EIO The trigger cannot be executed in the current state or a DMA
* channel cannot be allocated. * channel cannot be allocated.
* @retval -ENOMEM RX/TX memory block not available. * @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, __syscall int i2s_trigger(const struct device *dev, enum i2s_dir dir,
enum i2s_trigger_cmd cmd); enum i2s_trigger_cmd cmd);