Skip to content

Commit 1ecd7f1

Browse files
committed
driver: i2s: esp32: refactor trigger handling
Split i2s_esp32_trigger_stream() into smaller helper functions (handle_start, handle_stop, handle_drain) to reduce complexity and improve readability. No functional changes. Signed-off-by: Sylvio Alves <[email protected]>
1 parent 6a89a77 commit 1ecd7f1

File tree

1 file changed

+153
-131
lines changed

1 file changed

+153
-131
lines changed

drivers/i2s/i2s_esp32.c

Lines changed: 153 additions & 131 deletions
Original file line numberDiff line numberDiff line change
@@ -1193,169 +1193,188 @@ static const struct i2s_config *i2s_esp32_config_get(const struct device *dev, e
11931193
return &stream->data->i2s_cfg;
11941194
}
11951195

1196-
static int i2s_esp32_trigger_stream(const struct device *dev, const struct i2s_esp32_stream *stream,
1197-
enum i2s_dir dir, enum i2s_trigger_cmd cmd)
1196+
static inline bool tx_has_data(const struct i2s_esp32_stream *s)
11981197
{
1199-
const struct i2s_esp32_cfg *dev_cfg = dev->config;
1200-
const i2s_hal_context_t *hal = &dev_cfg->hal;
1201-
unsigned int key;
1202-
int err;
1203-
1204-
switch (cmd) {
1205-
case I2S_TRIGGER_START:
1206-
/* if already streaming, treat as success */
1207-
if (stream->data->state == I2S_STATE_RUNNING) {
1208-
LOG_DBG("START ignored: already RUNNING");
1209-
return 0;
1210-
}
1211-
if (stream->data->state != I2S_STATE_READY) {
1212-
LOG_ERR("START - Invalid state: %d", (int)stream->data->state);
1213-
return -EIO;
1214-
}
1198+
return k_msgq_num_used_get(&s->data->queue) > 0;
1199+
}
12151200

1216-
key = irq_lock();
1201+
static inline bool is_ready_or_running(const struct i2s_esp32_stream *s)
1202+
{
1203+
return s->data->state == I2S_STATE_READY || s->data->state == I2S_STATE_RUNNING;
1204+
}
12171205

1218-
if (dir == I2S_DIR_RX) {
1219-
i2s_hal_rx_stop(hal);
1220-
i2s_hal_rx_reset(hal);
1206+
static inline void reset_fifo(const i2s_hal_context_t *hal, enum i2s_dir dir)
1207+
{
1208+
if (dir == I2S_DIR_RX) {
1209+
i2s_hal_rx_stop(hal);
1210+
i2s_hal_rx_reset(hal);
12211211
#if !SOC_GDMA_SUPPORTED
1222-
i2s_hal_rx_reset_dma(hal);
1223-
#endif /* !SOC_GDMA_SUPPORTED */
1224-
i2s_hal_rx_reset_fifo(hal);
1225-
} else if (dir == I2S_DIR_TX) {
1226-
i2s_hal_tx_stop(hal);
1227-
i2s_hal_tx_reset(hal);
1212+
i2s_hal_rx_reset_dma(hal);
1213+
#endif
1214+
i2s_hal_rx_reset_fifo(hal);
1215+
} else {
1216+
i2s_hal_tx_stop(hal);
1217+
i2s_hal_tx_reset(hal);
12281218
#if !SOC_GDMA_SUPPORTED
1229-
i2s_hal_tx_reset_dma(hal);
1230-
#endif /* !SOC_GDMA_SUPPORTED */
1231-
i2s_hal_tx_reset_fifo(hal);
1232-
}
1219+
i2s_hal_tx_reset_dma(hal);
1220+
#endif
1221+
i2s_hal_tx_reset_fifo(hal);
1222+
}
1223+
}
12331224

1234-
err = stream->conf->start_transfer(dev);
1235-
if (err < 0) {
1236-
LOG_ERR("START - Transfer start failed: %d", err);
1237-
irq_unlock(key);
1238-
return -EIO;
1239-
}
1240-
stream->data->last_block = false;
1241-
/*
1242-
* If no mem_block was available (queue empty), stay READY.
1243-
* The next write() will auto-kick TX into RUNNING.
1244-
*/
1245-
if (dir == I2S_DIR_TX && stream->data->mem_block == NULL &&
1246-
!stream->data->dma_pending) {
1247-
stream->data->state = I2S_STATE_READY;
1248-
irq_unlock(key);
1249-
return 0;
1250-
}
1251-
stream->data->state = I2S_STATE_RUNNING;
1252-
irq_unlock(key);
1253-
break;
1225+
static int handle_start(const struct device *dev, const struct i2s_esp32_stream *stream,
1226+
enum i2s_dir dir, const i2s_hal_context_t *hal)
1227+
{
1228+
if (stream->data->state == I2S_STATE_RUNNING) {
1229+
LOG_DBG("START ignored: already RUNNING");
1230+
return 0;
1231+
}
1232+
if (stream->data->state != I2S_STATE_READY) {
1233+
LOG_ERR("START - Invalid state: %d", (int)stream->data->state);
1234+
return -EIO;
1235+
}
12541236

1255-
case I2S_TRIGGER_STOP:
1256-
key = irq_lock();
1257-
if (stream->data->state == I2S_STATE_READY) {
1258-
/* Already idle; treat STOP as success */
1259-
irq_unlock(key);
1260-
return 0;
1261-
}
1262-
if (stream->data->state != I2S_STATE_RUNNING) {
1263-
irq_unlock(key);
1264-
LOG_ERR("STOP - Invalid state: %d", (int)stream->data->state);
1265-
return -EIO;
1266-
}
1237+
reset_fifo(hal, dir);
12671238

1268-
if (stream->data->dma_pending) {
1269-
stream->data->stop_without_draining = true;
1270-
stream->data->state = I2S_STATE_STOPPING;
1271-
} else {
1272-
stream->conf->stop_transfer(dev);
1273-
stream->data->last_block = true;
1274-
stream->data->state = I2S_STATE_READY;
1275-
}
1239+
int err = stream->conf->start_transfer(dev);
12761240

1277-
irq_unlock(key);
1278-
break;
1241+
if (err < 0) {
1242+
LOG_ERR("START - Transfer start failed: %d", err);
1243+
return -EIO;
1244+
}
12791245

1280-
case I2S_TRIGGER_DRAIN:
1281-
key = irq_lock();
1282-
int32_t st = stream->data->state;
1246+
stream->data->last_block = false;
1247+
1248+
/* TX: if no mem_block was set (queue empty), remain READY */
1249+
if (dir == I2S_DIR_TX && stream->data->mem_block == NULL && !stream->data->dma_pending) {
1250+
stream->data->state = I2S_STATE_READY;
1251+
return 0;
1252+
}
1253+
1254+
stream->data->state = I2S_STATE_RUNNING;
1255+
return 0;
1256+
}
1257+
1258+
static int handle_stop(const struct device *dev, const struct i2s_esp32_stream *stream)
1259+
{
1260+
if (stream->data->state == I2S_STATE_READY) {
1261+
return 0; /* already idle */
1262+
}
1263+
if (stream->data->state != I2S_STATE_RUNNING) {
1264+
LOG_ERR("STOP - Invalid state: %d", (int)stream->data->state);
1265+
return -EIO;
1266+
}
1267+
1268+
if (stream->data->dma_pending) {
1269+
stream->data->stop_without_draining = true;
1270+
stream->data->state = I2S_STATE_STOPPING;
1271+
} else {
1272+
stream->conf->stop_transfer(dev);
1273+
stream->data->last_block = true;
1274+
stream->data->state = I2S_STATE_READY;
1275+
}
1276+
return 0;
1277+
}
1278+
1279+
static int handle_drain(const struct device *dev, const struct i2s_esp32_stream *stream,
1280+
enum i2s_dir dir)
1281+
{
1282+
int32_t st = stream->data->state;
12831283

1284-
if (st == I2S_STATE_READY) {
1284+
if (st != I2S_STATE_READY && st != I2S_STATE_RUNNING) {
1285+
LOG_ERR("DRAIN - Invalid state: %d", (int)st);
1286+
return -EIO;
1287+
}
1288+
1289+
if (st == I2S_STATE_READY) {
12851290
#if I2S_ESP32_IS_DIR_EN(tx)
1286-
if (dir == I2S_DIR_TX) {
1287-
bool have_data = (k_msgq_num_used_get(&stream->data->queue) > 0);
1288-
1289-
/* If there's data queued and TX is idle, kick once and drain */
1290-
if (have_data && !stream->data->dma_pending) {
1291-
int kick = stream->conf->start_transfer(dev);
1292-
1293-
if (kick < 0) {
1294-
irq_unlock(key);
1295-
LOG_ERR("DRAIN - autostart failed: %d", kick);
1296-
return -EIO;
1297-
}
1298-
stream->data->last_block = false;
1299-
stream->data->stop_without_draining = false;
1300-
stream->data->state = I2S_STATE_STOPPING;
1301-
irq_unlock(key);
1302-
break;
1303-
}
1291+
if (dir == I2S_DIR_TX) {
1292+
bool have_data = tx_has_data(stream);
1293+
1294+
/* If idle but data queued, kick once and drain */
1295+
if (have_data && !stream->data->dma_pending) {
1296+
int kick = stream->conf->start_transfer(dev);
13041297

1305-
/* Nothing to drain (idle and no queued blocks) */
1306-
if (!have_data && !stream->data->dma_pending) {
1307-
irq_unlock(key);
1308-
return 0;
1298+
if (kick < 0) {
1299+
LOG_ERR("DRAIN - autostart failed: %d", kick);
1300+
return -EIO;
13091301
}
1302+
stream->data->last_block = false;
1303+
stream->data->stop_without_draining = false;
1304+
stream->data->state = I2S_STATE_STOPPING;
1305+
return 0;
1306+
}
1307+
1308+
/* Idle and no data: nothing to drain */
1309+
if (!have_data && !stream->data->dma_pending) {
1310+
return 0;
13101311
}
1312+
}
13111313
#endif /* I2S_ESP32_IS_DIR_EN(tx) */
13121314

13131315
#if I2S_ESP32_IS_DIR_EN(rx)
1314-
if (dir == I2S_DIR_RX) {
1315-
/* If RX is idle and no DMA pending, nothing to drain */
1316-
if (!stream->data->dma_pending) {
1317-
irq_unlock(key);
1318-
return 0;
1319-
}
1316+
if (dir == I2S_DIR_RX) {
1317+
if (!stream->data->dma_pending) {
1318+
return 0; /* idle, no data */
13201319
}
1321-
#endif /* I2S_ESP32_IS_DIR_EN(rx) */
1322-
} else {
1323-
irq_unlock(key);
1324-
LOG_ERR("DRAIN - Invalid state: %d", (int)st);
1325-
return -EIO;
13261320
}
1321+
#endif /* I2S_ESP32_IS_DIR_EN(rx) */
1322+
}
13271323

1324+
/* Common tail: RUNNING, or READY with dma_pending */
13281325
#if I2S_ESP32_IS_DIR_EN(tx)
1329-
if (dir == I2S_DIR_TX) {
1330-
if (k_msgq_num_used_get(&stream->data->queue) > 0 ||
1331-
stream->data->dma_pending) {
1332-
stream->data->stop_without_draining = false;
1333-
stream->data->state = I2S_STATE_STOPPING;
1334-
} else {
1335-
stream->conf->stop_transfer(dev);
1336-
stream->data->state = I2S_STATE_READY;
1337-
}
1326+
if (dir == I2S_DIR_TX) {
1327+
if (tx_has_data(stream) || stream->data->dma_pending) {
1328+
stream->data->stop_without_draining = false;
1329+
stream->data->state = I2S_STATE_STOPPING;
1330+
} else {
1331+
stream->conf->stop_transfer(dev);
1332+
stream->data->state = I2S_STATE_READY;
13381333
}
1334+
}
13391335
#endif /* I2S_ESP32_IS_DIR_EN(tx) */
13401336

13411337
#if I2S_ESP32_IS_DIR_EN(rx)
1342-
if (dir == I2S_DIR_RX) {
1343-
if (stream->data->dma_pending) {
1344-
stream->data->stop_without_draining = true;
1345-
stream->data->state = I2S_STATE_STOPPING;
1346-
} else {
1347-
stream->conf->stop_transfer(dev);
1348-
stream->data->last_block = true;
1349-
stream->data->state = I2S_STATE_READY;
1350-
}
1338+
if (dir == I2S_DIR_RX) {
1339+
if (stream->data->dma_pending) {
1340+
stream->data->stop_without_draining = true;
1341+
stream->data->state = I2S_STATE_STOPPING;
1342+
} else {
1343+
stream->conf->stop_transfer(dev);
1344+
stream->data->last_block = true;
1345+
stream->data->state = I2S_STATE_READY;
13511346
}
1347+
}
13521348
#endif /* I2S_ESP32_IS_DIR_EN(rx) */
13531349

1354-
irq_unlock(key);
1350+
return 0;
1351+
}
1352+
1353+
static int i2s_esp32_trigger_stream(const struct device *dev, const struct i2s_esp32_stream *stream,
1354+
enum i2s_dir dir, enum i2s_trigger_cmd cmd)
1355+
{
1356+
const struct i2s_esp32_cfg *dev_cfg = dev->config;
1357+
const i2s_hal_context_t *hal = &dev_cfg->hal;
1358+
1359+
unsigned int key = irq_lock();
1360+
int ret = 0;
1361+
1362+
switch (cmd) {
1363+
case I2S_TRIGGER_START:
1364+
ret = handle_start(dev, stream, dir, hal);
1365+
break;
1366+
1367+
case I2S_TRIGGER_STOP:
1368+
ret = handle_stop(dev, stream);
1369+
break;
1370+
1371+
case I2S_TRIGGER_DRAIN:
1372+
ret = handle_drain(dev, stream, dir);
13551373
break;
13561374

13571375
case I2S_TRIGGER_DROP:
13581376
if (stream->data->state == I2S_STATE_NOT_READY) {
1377+
irq_unlock(key);
13591378
LOG_ERR("DROP - invalid state: %d", (int)stream->data->state);
13601379
return -EIO;
13611380
}
@@ -1366,6 +1385,7 @@ static int i2s_esp32_trigger_stream(const struct device *dev, const struct i2s_e
13661385

13671386
case I2S_TRIGGER_PREPARE:
13681387
if (stream->data->state != I2S_STATE_ERROR) {
1388+
irq_unlock(key);
13691389
LOG_ERR("PREPARE - invalid state: %d", (int)stream->data->state);
13701390
return -EIO;
13711391
}
@@ -1374,11 +1394,13 @@ static int i2s_esp32_trigger_stream(const struct device *dev, const struct i2s_e
13741394
break;
13751395

13761396
default:
1397+
irq_unlock(key);
13771398
LOG_ERR("Unsupported trigger command: %d", (int)cmd);
13781399
return -EINVAL;
13791400
}
13801401

1381-
return 0;
1402+
irq_unlock(key);
1403+
return ret;
13821404
}
13831405

13841406
static int i2s_esp32_trigger(const struct device *dev, enum i2s_dir dir, enum i2s_trigger_cmd cmd)

0 commit comments

Comments
 (0)