@@ -1332,19 +1332,15 @@ int dai_zephyr_multi_endpoint_copy(struct dai_data **dd, struct comp_dev *dev,
13321332 struct comp_buffer * multi_endpoint_buffer ,
13331333 int num_endpoints )
13341334{
1335- uint32_t avail_bytes = UINT32_MAX ;
1336- uint32_t free_bytes = UINT32_MAX ;
1337- uint32_t frames ;
1338- uint32_t src_frames , sink_frames ;
13391335 uint32_t frame_bytes ;
1336+ uint32_t frames_aligned ;
1337+ uint32_t frames = UINT32_MAX ;
13401338 int ret , i ;
13411339 int direction ;
13421340
13431341 if (!num_endpoints || !dd || !multi_endpoint_buffer )
13441342 return 0 ;
13451343
1346- frame_bytes = audio_stream_frame_bytes (& dd [0 ]-> dma_buffer -> stream );
1347-
13481344 direction = dev -> direction ;
13491345
13501346 /* calculate min available/free from all endpoint DMA buffers */
@@ -1359,37 +1355,40 @@ int dai_zephyr_multi_endpoint_copy(struct dai_data **dd, struct comp_dev *dev,
13591355 case - EPIPE :
13601356 /* DMA status can return -EPIPE and current status content if xrun occurs */
13611357 if (direction == SOF_IPC_STREAM_PLAYBACK )
1362- comp_dbg (dev , "dai_zephyr_multi_endpoint_copy(): dma_get_status() underrun occurred, endpoint: %d ret = %u" ,
1358+ comp_dbg (dev , "dma_get_status() underrun occurred endpoint: %d ret = %u" ,
13631359 i , ret );
13641360 else
1365- comp_dbg (dev , "dai_zephyr_multi_endpoint_copy(): dma_get_status() overrun occurred, enpdoint: %d ret = %u" ,
1361+ comp_dbg (dev , "dma_get_status() overrun occurred, enpdoint: %d ret = %u" ,
13661362 i , ret );
13671363 break ;
13681364 default :
13691365 return ret ;
13701366 }
13711367
1372- avail_bytes = MIN ( avail_bytes , stat . pending_length );
1373- free_bytes = MIN ( free_bytes , stat . free );
1374- }
1375-
1376- /* calculate minimum size to copy */
1377- if ( direction == SOF_IPC_STREAM_PLAYBACK ) {
1378- src_frames = audio_stream_get_avail_frames ( & multi_endpoint_buffer -> stream );
1379- sink_frames = free_bytes / frame_bytes ;
1380- } else {
1381- src_frames = avail_bytes / frame_bytes ;
1382- sink_frames = audio_stream_get_free_frames ( & multi_endpoint_buffer -> stream );
1368+ /* Use frames_aligned here to avoid glitches, especially for streams with
1369+ * odd number of channels */
1370+ if ( direction == SOF_IPC_STREAM_PLAYBACK ) {
1371+ frames_aligned = audio_stream_avail_frames_aligned (
1372+ & multi_endpoint_buffer -> stream , & dd [ i ] -> dma_buffer -> stream );
1373+ frames = MIN ( frames , frames_aligned );
1374+ } else {
1375+ frames_aligned = audio_stream_avail_frames_aligned (
1376+ & dd [ i ] -> dma_buffer -> stream , & multi_endpoint_buffer -> stream );
1377+ frames = MIN ( frames , frames_aligned ) ;
1378+ }
13831379 }
13841380
1385- frames = MIN (src_frames , sink_frames );
1386-
13871381 /* limit bytes per copy to one period for the whole pipeline in order to avoid high load
13881382 * spike if FAST_MODE is enabled, then one period limitation is omitted. All dd's have the
13891383 * same period_bytes, so use the period_bytes from dd[0]
13901384 */
1391- if (!(dd [0 ]-> ipc_config .feature_mask & BIT (IPC4_COPIER_FAST_MODE )))
1392- frames = MIN (frames , dd [0 ]-> period_bytes / frame_bytes );
1385+ if (!dd [0 ]-> fast_mode ) {
1386+ size_t period_frames = dd [0 ]-> period_bytes /
1387+ audio_stream_frame_bytes (& dd [0 ]-> dma_buffer -> stream );
1388+ if (period_frames < frames )
1389+ frames = period_frames ;
1390+ }
1391+
13931392 comp_dbg (dev , "dai_zephyr_multi_endpoint_copy(), dir: %d copy frames= 0x%x" ,
13941393 dev -> direction , frames );
13951394
0 commit comments