@@ -1193,169 +1193,185 @@ static const struct i2s_config *i2s_esp32_config_get(const struct device *dev, e
1193
1193
return & stream -> data -> i2s_cfg ;
1194
1194
}
1195
1195
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 )
1198
1197
{
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
+ }
1215
1200
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
+ }
1217
1205
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 );
1221
1211
#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 );
1228
1218
#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
+ }
1233
1224
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
+ }
1254
1236
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 );
1267
1238
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 );
1276
1240
1277
- irq_unlock (key );
1278
- break ;
1241
+ if (err < 0 ) {
1242
+ LOG_ERR ("START - Transfer start failed: %d" , err );
1243
+ return - EIO ;
1244
+ }
1279
1245
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
+ }
1283
1267
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 ) {
1285
1285
#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 );
1304
1292
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 ;
1309
1296
}
1297
+ stream -> data -> last_block = false;
1298
+ stream -> data -> stop_without_draining = false;
1299
+ stream -> data -> state = I2S_STATE_STOPPING ;
1300
+ return 0 ;
1310
1301
}
1302
+
1303
+ /* Idle and no data: nothing to drain */
1304
+ if (!have_data && !stream -> data -> dma_pending ) {
1305
+ return 0 ;
1306
+ }
1307
+ }
1311
1308
#endif /* I2S_ESP32_IS_DIR_EN(tx) */
1312
1309
1313
1310
#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 */
1320
1314
}
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 ;
1326
1315
}
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
+ }
1327
1321
1328
1322
#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 ;
1338
1330
}
1331
+ }
1339
1332
#endif /* I2S_ESP32_IS_DIR_EN(tx) */
1340
1333
1341
1334
#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 ;
1351
1343
}
1344
+ }
1352
1345
#endif /* I2S_ESP32_IS_DIR_EN(rx) */
1353
1346
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 );
1355
1370
break ;
1356
1371
1357
1372
case I2S_TRIGGER_DROP :
1358
1373
if (stream -> data -> state == I2S_STATE_NOT_READY ) {
1374
+ irq_unlock (key );
1359
1375
LOG_ERR ("DROP - invalid state: %d" , (int )stream -> data -> state );
1360
1376
return - EIO ;
1361
1377
}
@@ -1366,6 +1382,7 @@ static int i2s_esp32_trigger_stream(const struct device *dev, const struct i2s_e
1366
1382
1367
1383
case I2S_TRIGGER_PREPARE :
1368
1384
if (stream -> data -> state != I2S_STATE_ERROR ) {
1385
+ irq_unlock (key );
1369
1386
LOG_ERR ("PREPARE - invalid state: %d" , (int )stream -> data -> state );
1370
1387
return - EIO ;
1371
1388
}
@@ -1374,11 +1391,13 @@ static int i2s_esp32_trigger_stream(const struct device *dev, const struct i2s_e
1374
1391
break ;
1375
1392
1376
1393
default :
1394
+ irq_unlock (key );
1377
1395
LOG_ERR ("Unsupported trigger command: %d" , (int )cmd );
1378
1396
return - EINVAL ;
1379
1397
}
1380
1398
1381
- return 0 ;
1399
+ irq_unlock (key );
1400
+ return ret ;
1382
1401
}
1383
1402
1384
1403
static int i2s_esp32_trigger (const struct device * dev , enum i2s_dir dir , enum i2s_trigger_cmd cmd )
0 commit comments