@@ -1334,19 +1334,15 @@ int dai_zephyr_multi_endpoint_copy(struct dai_data **dd, struct comp_dev *dev,
13341334 struct comp_buffer * multi_endpoint_buffer ,
13351335 int num_endpoints )
13361336{
1337- uint32_t avail_bytes = UINT32_MAX ;
1338- uint32_t free_bytes = UINT32_MAX ;
1339- uint32_t frames ;
1340- uint32_t src_frames , sink_frames ;
13411337 uint32_t frame_bytes ;
1338+ uint32_t frames_aligned ;
1339+ uint32_t frames = UINT32_MAX ;
13421340 int ret , i ;
13431341 int direction ;
13441342
13451343 if (!num_endpoints || !dd || !multi_endpoint_buffer )
13461344 return 0 ;
13471345
1348- frame_bytes = audio_stream_frame_bytes (& dd [0 ]-> dma_buffer -> stream );
1349-
13501346 direction = dev -> direction ;
13511347
13521348 /* calculate min available/free from all endpoint DMA buffers */
@@ -1361,37 +1357,41 @@ int dai_zephyr_multi_endpoint_copy(struct dai_data **dd, struct comp_dev *dev,
13611357 case - EPIPE :
13621358 /* DMA status can return -EPIPE and current status content if xrun occurs */
13631359 if (direction == SOF_IPC_STREAM_PLAYBACK )
1364- comp_dbg (dev , "dai_zephyr_multi_endpoint_copy(): dma_get_status() underrun occurred, endpoint: %d ret = %u" ,
1360+ comp_dbg (dev , "dma_get_status() underrun occurred endpoint: %d ret = %u" ,
13651361 i , ret );
13661362 else
1367- comp_dbg (dev , "dai_zephyr_multi_endpoint_copy(): dma_get_status() overrun occurred, enpdoint: %d ret = %u" ,
1363+ comp_dbg (dev , "dma_get_status() overrun occurred, enpdoint: %d ret = %u" ,
13681364 i , ret );
13691365 break ;
13701366 default :
13711367 return ret ;
13721368 }
13731369
1374- avail_bytes = MIN (avail_bytes , stat .pending_length );
1375- free_bytes = MIN (free_bytes , stat .free );
1376- }
1377-
1378- /* calculate minimum size to copy */
1379- if (direction == SOF_IPC_STREAM_PLAYBACK ) {
1380- src_frames = audio_stream_get_avail_frames (& multi_endpoint_buffer -> stream );
1381- sink_frames = free_bytes / frame_bytes ;
1382- } else {
1383- src_frames = avail_bytes / frame_bytes ;
1384- sink_frames = audio_stream_get_free_frames (& multi_endpoint_buffer -> stream );
1370+ /* Use frames_aligned here to avoid glitches, especially for streams
1371+ * with odd number of channels. Update frames for every dai in a loop.
1372+ */
1373+ if (direction == SOF_IPC_STREAM_PLAYBACK )
1374+ frames_aligned =
1375+ audio_stream_avail_frames_aligned (& multi_endpoint_buffer -> stream ,
1376+ & dd [i ]-> dma_buffer -> stream );
1377+ else
1378+ frames_aligned =
1379+ audio_stream_avail_frames_aligned (& dd [i ]-> dma_buffer -> stream ,
1380+ & multi_endpoint_buffer -> stream );
1381+ frames = MIN (frames , frames_aligned );
13851382 }
13861383
1387- frames = MIN (src_frames , sink_frames );
1388-
13891384 /* limit bytes per copy to one period for the whole pipeline in order to avoid high load
13901385 * spike if FAST_MODE is enabled, then one period limitation is omitted. All dd's have the
13911386 * same period_bytes, so use the period_bytes from dd[0]
13921387 */
1393- if (!(dd [0 ]-> ipc_config .feature_mask & BIT (IPC4_COPIER_FAST_MODE )))
1394- frames = MIN (frames , dd [0 ]-> period_bytes / frame_bytes );
1388+ if (!dd [0 ]-> fast_mode ) {
1389+ size_t period_frames = dd [0 ]-> period_bytes /
1390+ audio_stream_frame_bytes (& dd [0 ]-> dma_buffer -> stream );
1391+ if (period_frames < frames )
1392+ frames = period_frames ;
1393+ }
1394+
13951395 comp_dbg (dev , "dai_zephyr_multi_endpoint_copy(), dir: %d copy frames= 0x%x" ,
13961396 dev -> direction , frames );
13971397
0 commit comments