Skip to content

Commit 8d0811e

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 12043ed commit 8d0811e

File tree

1 file changed

+150
-131
lines changed

1 file changed

+150
-131
lines changed

drivers/i2s/i2s_esp32.c

Lines changed: 150 additions & 131 deletions
Original file line numberDiff line numberDiff line change
@@ -1193,169 +1193,185 @@ 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+
}
12831267

1284-
if (st == I2S_STATE_READY) {
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;
1283+
1284+
if (st == I2S_STATE_READY) {
12851285
#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-
}
1286+
if (dir == I2S_DIR_TX) {
1287+
bool have_data = tx_has_data(stream);
1288+
1289+
/* If idle but data queued, kick once and drain */
1290+
if (have_data && !stream->data->dma_pending) {
1291+
int kick = stream->conf->start_transfer(dev);
13041292

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

13131310
#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-
}
1311+
if (dir == I2S_DIR_RX) {
1312+
if (!stream->data->dma_pending) {
1313+
return 0; /* idle, no data */
13201314
}
1321-
#endif /* I2S_ESP32_IS_DIR_EN(rx) */
1322-
} else if (st != I2S_STATE_RUNNING) {
1323-
irq_unlock(key);
1324-
LOG_ERR("DRAIN - Invalid state: %d", (int)st);
1325-
return -EIO;
13261315
}
1316+
#endif /* I2S_ESP32_IS_DIR_EN(rx) */
1317+
} else if (st != I2S_STATE_RUNNING) {
1318+
LOG_ERR("DRAIN - Invalid state: %d", (int)st);
1319+
return -EIO;
1320+
}
13271321

13281322
#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-
}
1323+
if (dir == I2S_DIR_TX) {
1324+
if (tx_has_data(stream) || stream->data->dma_pending) {
1325+
stream->data->stop_without_draining = false;
1326+
stream->data->state = I2S_STATE_STOPPING;
1327+
} else {
1328+
stream->conf->stop_transfer(dev);
1329+
stream->data->state = I2S_STATE_READY;
13381330
}
1331+
}
13391332
#endif /* I2S_ESP32_IS_DIR_EN(tx) */
13401333

13411334
#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-
}
1335+
if (dir == I2S_DIR_RX) {
1336+
if (stream->data->dma_pending) {
1337+
stream->data->stop_without_draining = true;
1338+
stream->data->state = I2S_STATE_STOPPING;
1339+
} else {
1340+
stream->conf->stop_transfer(dev);
1341+
stream->data->last_block = true;
1342+
stream->data->state = I2S_STATE_READY;
13511343
}
1344+
}
13521345
#endif /* I2S_ESP32_IS_DIR_EN(rx) */
13531346

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

13571372
case I2S_TRIGGER_DROP:
13581373
if (stream->data->state == I2S_STATE_NOT_READY) {
1374+
irq_unlock(key);
13591375
LOG_ERR("DROP - invalid state: %d", (int)stream->data->state);
13601376
return -EIO;
13611377
}
@@ -1366,6 +1382,7 @@ static int i2s_esp32_trigger_stream(const struct device *dev, const struct i2s_e
13661382

13671383
case I2S_TRIGGER_PREPARE:
13681384
if (stream->data->state != I2S_STATE_ERROR) {
1385+
irq_unlock(key);
13691386
LOG_ERR("PREPARE - invalid state: %d", (int)stream->data->state);
13701387
return -EIO;
13711388
}
@@ -1374,11 +1391,13 @@ static int i2s_esp32_trigger_stream(const struct device *dev, const struct i2s_e
13741391
break;
13751392

13761393
default:
1394+
irq_unlock(key);
13771395
LOG_ERR("Unsupported trigger command: %d", (int)cmd);
13781396
return -EINVAL;
13791397
}
13801398

1381-
return 0;
1399+
irq_unlock(key);
1400+
return ret;
13821401
}
13831402

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

0 commit comments

Comments
 (0)