drivers: i2s_mcux_sai: Cleanup dma callbacks

The dma callback functions were written in a very confusing way, clean
them up, and this change also saves some bytes of ROM.

Signed-off-by: Declan Snyder <declan.snyder@nxp.com>
This commit is contained in:
Declan Snyder 2024-11-20 18:30:22 -06:00 committed by Benjamin Cabé
parent d22607ae27
commit 3c1dcf346c

View file

@ -255,9 +255,9 @@ static void i2s_dma_tx_callback(const struct device *dma_dev, void *arg, uint32_
const struct device *dev = (struct device *)arg; const struct device *dev = (struct device *)arg;
struct i2s_dev_data *dev_data = dev->data; struct i2s_dev_data *dev_data = dev->data;
struct stream *strm = &dev_data->tx; struct stream *strm = &dev_data->tx;
uint8_t blocks_queued;
void *buffer = NULL; void *buffer = NULL;
int ret; int ret;
uint8_t blocks_queued;
LOG_DBG("tx cb"); LOG_DBG("tx cb");
@ -289,36 +289,31 @@ static void i2s_dma_tx_callback(const struct device *dma_dev, void *arg, uint32_
goto disabled_exit_no_drop; goto disabled_exit_no_drop;
} }
switch (strm->state) { if (strm->state != I2S_STATE_RUNNING && strm->state != I2S_STATE_STOPPING) {
case I2S_STATE_RUNNING:
case I2S_STATE_STOPPING:
ret = i2s_tx_reload_multiple_dma_blocks(dev, &blocks_queued);
if (ret) {
strm->state = I2S_STATE_ERROR;
goto disabled_exit_no_drop;
}
if (blocks_queued || (strm->free_tx_dma_blocks < MAX_TX_DMA_BLOCKS)) {
goto enabled_exit;
} else {
/* all DMA blocks are free but no blocks were queued */
if (strm->state == I2S_STATE_STOPPING) {
/* TX queue has drained */
strm->state = I2S_STATE_READY;
LOG_DBG("TX stream has stopped");
} else {
strm->state = I2S_STATE_ERROR;
LOG_ERR("TX Failed to reload DMA");
}
goto disabled_exit_no_drop;
}
case I2S_STATE_ERROR:
default:
goto disabled_exit_drop; goto disabled_exit_drop;
} }
ret = i2s_tx_reload_multiple_dma_blocks(dev, &blocks_queued);
if (ret) {
strm->state = I2S_STATE_ERROR;
goto disabled_exit_no_drop;
}
if (blocks_queued || (strm->free_tx_dma_blocks < MAX_TX_DMA_BLOCKS)) {
goto enabled_exit;
}
/* all DMA blocks are free but no blocks were queued */
if (strm->state == I2S_STATE_STOPPING) {
/* TX queue has drained */
strm->state = I2S_STATE_READY;
LOG_DBG("TX stream has stopped");
} else {
strm->state = I2S_STATE_ERROR;
LOG_ERR("TX Failed to reload DMA");
}
goto disabled_exit_no_drop;
disabled_exit_no_drop: disabled_exit_no_drop:
i2s_tx_stream_disable(dev, false); i2s_tx_stream_disable(dev, false);
return; return;
@ -344,61 +339,62 @@ static void i2s_dma_rx_callback(const struct device *dma_dev, void *arg, uint32_
LOG_DBG("RX cb"); LOG_DBG("RX cb");
switch (strm->state) { if (strm->state == I2S_STATE_ERROR) {
case I2S_STATE_STOPPING:
case I2S_STATE_RUNNING:
/* retrieve buffer from input queue */
ret = k_msgq_get(&strm->in_queue, &buffer, K_NO_WAIT);
__ASSERT_NO_MSG(ret == 0);
/* put buffer to output queue */
ret = k_msgq_put(&strm->out_queue, &buffer, K_NO_WAIT);
if (ret != 0) {
LOG_ERR("buffer %p -> out_queue %p err %d", buffer, &strm->out_queue, ret);
i2s_rx_stream_disable(dev, false, false);
strm->state = I2S_STATE_ERROR;
return;
}
if (strm->state == I2S_STATE_RUNNING) {
/* allocate new buffer for next audio frame */
ret = k_mem_slab_alloc(strm->cfg.mem_slab, &buffer, K_NO_WAIT);
if (ret != 0) {
LOG_ERR("buffer alloc from slab %p err %d", strm->cfg.mem_slab,
ret);
i2s_rx_stream_disable(dev, false, false);
strm->state = I2S_STATE_ERROR;
} else {
uint32_t data_path = strm->start_channel;
ret = dma_reload(dev_data->dev_dma, strm->dma_channel,
(uint32_t)&base->RDR[data_path], (uint32_t)buffer,
strm->cfg.block_size);
if (ret != 0) {
LOG_ERR("dma_reload() failed with error 0x%x", ret);
i2s_rx_stream_disable(dev, false, false);
strm->state = I2S_STATE_ERROR;
return;
}
/* put buffer in input queue */
ret = k_msgq_put(&strm->in_queue, &buffer, K_NO_WAIT);
if (ret != 0) {
LOG_ERR("%p -> in_queue %p err %d", buffer, &strm->in_queue,
ret);
}
}
} else {
i2s_rx_stream_disable(dev, true, false);
/* Received a STOP/DRAIN trigger */
strm->state = I2S_STATE_READY;
}
break;
case I2S_STATE_ERROR:
i2s_rx_stream_disable(dev, true, true); i2s_rx_stream_disable(dev, true, true);
break;
default:
break;
} }
if (strm->state != I2S_STATE_STOPPING && strm->state != I2S_STATE_RUNNING) {
return;
}
/* retrieve buffer from input queue */
ret = k_msgq_get(&strm->in_queue, &buffer, K_NO_WAIT);
__ASSERT_NO_MSG(ret == 0);
/* put buffer to output queue */
ret = k_msgq_put(&strm->out_queue, &buffer, K_NO_WAIT);
if (ret != 0) {
LOG_ERR("buffer %p -> out_queue %p err %d", buffer, &strm->out_queue, ret);
goto error;
}
if (strm->state == I2S_STATE_STOPPING) {
i2s_rx_stream_disable(dev, true, false);
/* Received a STOP/DRAIN trigger */
strm->state = I2S_STATE_READY;
return;
}
/* Now the only possible case is the running state */
/* allocate new buffer for next audio frame */
ret = k_mem_slab_alloc(strm->cfg.mem_slab, &buffer, K_NO_WAIT);
if (ret != 0) {
LOG_ERR("buffer alloc from slab %p err %d", strm->cfg.mem_slab, ret);
goto error;
}
uint32_t data_path = strm->start_channel;
ret = dma_reload(dev_data->dev_dma, strm->dma_channel,
(uint32_t)&base->RDR[data_path], (uint32_t)buffer,
strm->cfg.block_size);
if (ret != 0) {
LOG_ERR("dma_reload() failed with error 0x%x", ret);
goto error;
}
/* put buffer in input queue */
ret = k_msgq_put(&strm->in_queue, &buffer, K_NO_WAIT);
if (ret != 0) {
LOG_ERR("%p -> in_queue %p err %d", buffer, &strm->in_queue, ret);
}
return;
error:
i2s_rx_stream_disable(dev, false, false);
strm->state = I2S_STATE_ERROR;
} }
static void enable_mclk_direction(const struct device *dev, bool dir) static void enable_mclk_direction(const struct device *dev, bool dir)