@@ -143,6 +143,7 @@ struct fsl_ssi_private {
143
143
bool ssi_on_imx ;
144
144
bool imx_ac97 ;
145
145
bool use_dma ;
146
+ bool use_dual_fifo ;
146
147
struct clk * clk ;
147
148
struct snd_dmaengine_dai_dma_data dma_params_tx ;
148
149
struct snd_dmaengine_dai_dma_data dma_params_rx ;
@@ -413,6 +414,12 @@ static int fsl_ssi_setup(struct fsl_ssi_private *ssi_private)
413
414
write_ssi (CCSR_SSI_SOR_WAIT (3 ), & ssi -> sor );
414
415
}
415
416
417
+ if (ssi_private -> use_dual_fifo ) {
418
+ write_ssi_mask (& ssi -> srcr , 0 , CCSR_SSI_SRCR_RFEN1 );
419
+ write_ssi_mask (& ssi -> stcr , 0 , CCSR_SSI_STCR_TFEN1 );
420
+ write_ssi_mask (& ssi -> scr , 0 , CCSR_SSI_SCR_TCH_EN );
421
+ }
422
+
416
423
return 0 ;
417
424
}
418
425
@@ -480,6 +487,15 @@ static int fsl_ssi_startup(struct snd_pcm_substream *substream,
480
487
ssi_private -> second_stream = substream ;
481
488
}
482
489
490
+ /* When using dual fifo mode, it is safer to ensure an even period
491
+ * size. If appearing to an odd number while DMA always starts its
492
+ * task from fifo0, fifo1 would be neglected at the end of each
493
+ * period. But SSI would still access fifo1 with an invalid data.
494
+ */
495
+ if (ssi_private -> use_dual_fifo )
496
+ snd_pcm_hw_constraint_step (substream -> runtime , 0 ,
497
+ SNDRV_PCM_HW_PARAM_PERIOD_SIZE , 2 );
498
+
483
499
return 0 ;
484
500
}
485
501
@@ -947,7 +963,7 @@ static int fsl_ssi_probe(struct platform_device *pdev)
947
963
ssi_private -> fifo_depth = 8 ;
948
964
949
965
if (of_device_is_compatible (pdev -> dev .of_node , "fsl,imx21-ssi" )) {
950
- u32 dma_events [2 ];
966
+ u32 dma_events [2 ], dmas [ 4 ] ;
951
967
ssi_private -> ssi_on_imx = true;
952
968
953
969
ssi_private -> clk = devm_clk_get (& pdev -> dev , NULL );
@@ -1001,6 +1017,15 @@ static int fsl_ssi_probe(struct platform_device *pdev)
1001
1017
dma_events [0 ], shared ? IMX_DMATYPE_SSI_SP : IMX_DMATYPE_SSI );
1002
1018
imx_pcm_dma_params_init_data (& ssi_private -> filter_data_rx ,
1003
1019
dma_events [1 ], shared ? IMX_DMATYPE_SSI_SP : IMX_DMATYPE_SSI );
1020
+ if (!of_property_read_u32_array (pdev -> dev .of_node , "dmas" , dmas , 4 )
1021
+ && dmas [2 ] == IMX_DMATYPE_SSI_DUAL ) {
1022
+ ssi_private -> use_dual_fifo = true;
1023
+ /* When using dual fifo mode, we need to keep watermark
1024
+ * as even numbers due to dma script limitation.
1025
+ */
1026
+ ssi_private -> dma_params_tx .maxburst &= ~0x1 ;
1027
+ ssi_private -> dma_params_rx .maxburst &= ~0x1 ;
1028
+ }
1004
1029
} else if (ssi_private -> use_dma ) {
1005
1030
/* The 'name' should not have any slashes in it. */
1006
1031
ret = devm_request_irq (& pdev -> dev , ssi_private -> irq ,
0 commit comments