1717#include <sound/pcm_params.h>
1818#include <sound/soc.h>
1919
20- struct qmc_dai_chan {
21- struct qmc_dai_prtd * prtd_tx ;
22- struct qmc_dai_prtd * prtd_rx ;
23- struct qmc_chan * qmc_chan ;
24- };
25-
2620struct qmc_dai {
2721 char * name ;
2822 int id ;
@@ -33,7 +27,7 @@ struct qmc_dai {
3327 unsigned int nb_chans_avail ;
3428 unsigned int nb_chans_used_tx ;
3529 unsigned int nb_chans_used_rx ;
36- struct qmc_dai_chan * chans ;
30+ struct qmc_chan * * qmc_chans ;
3731};
3832
3933struct qmc_audio {
@@ -57,7 +51,6 @@ struct qmc_dai_prtd {
5751 size_t ch_dma_offset ;
5852
5953 unsigned int channels ;
60- DECLARE_BITMAP (chans_pending , 64 );
6154 struct snd_pcm_substream * substream ;
6255};
6356
@@ -126,17 +119,14 @@ static int qmc_audio_pcm_write_submit(struct qmc_dai_prtd *prtd)
126119 int ret ;
127120
128121 for (i = 0 ; i < prtd -> channels ; i ++ ) {
129- bitmap_set (prtd -> chans_pending , i , 1 );
130-
131- ret = qmc_chan_write_submit (prtd -> qmc_dai -> chans [i ].qmc_chan ,
122+ ret = qmc_chan_write_submit (prtd -> qmc_dai -> qmc_chans [i ],
132123 prtd -> ch_dma_addr_current + i * prtd -> ch_dma_offset ,
133124 prtd -> ch_dma_size ,
134- qmc_audio_pcm_write_complete ,
135- & prtd -> qmc_dai -> chans [ i ] );
125+ i == prtd -> channels - 1 ? qmc_audio_pcm_write_complete :
126+ NULL , prtd );
136127 if (ret ) {
137128 dev_err (prtd -> qmc_dai -> dev , "write_submit %u failed %d\n" ,
138129 i , ret );
139- bitmap_clear (prtd -> chans_pending , i , 1 );
140130 return ret ;
141131 }
142132 }
@@ -146,20 +136,7 @@ static int qmc_audio_pcm_write_submit(struct qmc_dai_prtd *prtd)
146136
147137static void qmc_audio_pcm_write_complete (void * context )
148138{
149- struct qmc_dai_chan * chan = context ;
150- struct qmc_dai_prtd * prtd ;
151-
152- prtd = chan -> prtd_tx ;
153-
154- /* Mark the current channel as completed */
155- bitmap_clear (prtd -> chans_pending , chan - prtd -> qmc_dai -> chans , 1 );
156-
157- /*
158- * All QMC channels involved must have completed their transfer before
159- * submitting a new one.
160- */
161- if (!bitmap_empty (prtd -> chans_pending , 64 ))
162- return ;
139+ struct qmc_dai_prtd * prtd = context ;
163140
164141 prtd -> buffer_ended += prtd -> period_size ;
165142 if (prtd -> buffer_ended >= prtd -> buffer_size )
@@ -182,17 +159,14 @@ static int qmc_audio_pcm_read_submit(struct qmc_dai_prtd *prtd)
182159 int ret ;
183160
184161 for (i = 0 ; i < prtd -> channels ; i ++ ) {
185- bitmap_set (prtd -> chans_pending , i , 1 );
186-
187- ret = qmc_chan_read_submit (prtd -> qmc_dai -> chans [i ].qmc_chan ,
162+ ret = qmc_chan_read_submit (prtd -> qmc_dai -> qmc_chans [i ],
188163 prtd -> ch_dma_addr_current + i * prtd -> ch_dma_offset ,
189164 prtd -> ch_dma_size ,
190- qmc_audio_pcm_read_complete ,
191- & prtd -> qmc_dai -> chans [ i ] );
165+ i == prtd -> channels - 1 ? qmc_audio_pcm_read_complete :
166+ NULL , prtd );
192167 if (ret ) {
193168 dev_err (prtd -> qmc_dai -> dev , "read_submit %u failed %d\n" ,
194169 i , ret );
195- bitmap_clear (prtd -> chans_pending , i , 1 );
196170 return ret ;
197171 }
198172 }
@@ -202,26 +176,13 @@ static int qmc_audio_pcm_read_submit(struct qmc_dai_prtd *prtd)
202176
203177static void qmc_audio_pcm_read_complete (void * context , size_t length , unsigned int flags )
204178{
205- struct qmc_dai_chan * chan = context ;
206- struct qmc_dai_prtd * prtd ;
207-
208- prtd = chan -> prtd_rx ;
209-
210- /* Mark the current channel as completed */
211- bitmap_clear (prtd -> chans_pending , chan - prtd -> qmc_dai -> chans , 1 );
179+ struct qmc_dai_prtd * prtd = context ;
212180
213181 if (length != prtd -> ch_dma_size ) {
214182 dev_err (prtd -> qmc_dai -> dev , "read complete length = %zu, exp %zu\n" ,
215183 length , prtd -> ch_dma_size );
216184 }
217185
218- /*
219- * All QMC channels involved must have completed their transfer before
220- * submitting a new one.
221- */
222- if (!bitmap_empty (prtd -> chans_pending , 64 ))
223- return ;
224-
225186 prtd -> buffer_ended += prtd -> period_size ;
226187 if (prtd -> buffer_ended >= prtd -> buffer_size )
227188 prtd -> buffer_ended = 0 ;
@@ -239,7 +200,6 @@ static int qmc_audio_pcm_trigger(struct snd_soc_component *component,
239200 struct snd_pcm_substream * substream , int cmd )
240201{
241202 struct qmc_dai_prtd * prtd = substream -> runtime -> private_data ;
242- unsigned int i ;
243203 int ret ;
244204
245205 if (!prtd -> qmc_dai ) {
@@ -249,14 +209,10 @@ static int qmc_audio_pcm_trigger(struct snd_soc_component *component,
249209
250210 switch (cmd ) {
251211 case SNDRV_PCM_TRIGGER_START :
252- bitmap_zero (prtd -> chans_pending , 64 );
253212 prtd -> buffer_ended = 0 ;
254213 prtd -> ch_dma_addr_current = prtd -> ch_dma_addr_start ;
255214
256215 if (substream -> stream == SNDRV_PCM_STREAM_PLAYBACK ) {
257- for (i = 0 ; i < prtd -> channels ; i ++ )
258- prtd -> qmc_dai -> chans [i ].prtd_tx = prtd ;
259-
260216 /* Submit first chunk ... */
261217 ret = qmc_audio_pcm_write_submit (prtd );
262218 if (ret )
@@ -272,9 +228,6 @@ static int qmc_audio_pcm_trigger(struct snd_soc_component *component,
272228 if (ret )
273229 return ret ;
274230 } else {
275- for (i = 0 ; i < prtd -> channels ; i ++ )
276- prtd -> qmc_dai -> chans [i ].prtd_rx = prtd ;
277-
278231 /* Submit first chunk ... */
279232 ret = qmc_audio_pcm_read_submit (prtd );
280233 if (ret )
@@ -644,9 +597,9 @@ static int qmc_dai_hw_params(struct snd_pcm_substream *substream,
644597 chan_param .mode = QMC_TRANSPARENT ;
645598 chan_param .transp .max_rx_buf_size = params_period_bytes (params ) / nb_chans_used ;
646599 for (i = 0 ; i < nb_chans_used ; i ++ ) {
647- ret = qmc_chan_set_param (qmc_dai -> chans [i ]. qmc_chan , & chan_param );
600+ ret = qmc_chan_set_param (qmc_dai -> qmc_chans [i ], & chan_param );
648601 if (ret ) {
649- dev_err (dai -> dev , "chans [%u], set param failed %d\n" ,
602+ dev_err (dai -> dev , "qmc_chans [%u], set param failed %d\n" ,
650603 i , ret );
651604 return ret ;
652605 }
@@ -688,7 +641,7 @@ static int qmc_dai_trigger(struct snd_pcm_substream *substream, int cmd,
688641 case SNDRV_PCM_TRIGGER_RESUME :
689642 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE :
690643 for (i = 0 ; i < nb_chans_used ; i ++ ) {
691- ret = qmc_chan_start (qmc_dai -> chans [i ]. qmc_chan , direction );
644+ ret = qmc_chan_start (qmc_dai -> qmc_chans [i ], direction );
692645 if (ret )
693646 goto err_stop ;
694647 }
@@ -697,13 +650,13 @@ static int qmc_dai_trigger(struct snd_pcm_substream *substream, int cmd,
697650 case SNDRV_PCM_TRIGGER_STOP :
698651 /* Stop and reset all QMC channels and return the first error encountered */
699652 for (i = 0 ; i < nb_chans_used ; i ++ ) {
700- ret_tmp = qmc_chan_stop (qmc_dai -> chans [i ]. qmc_chan , direction );
653+ ret_tmp = qmc_chan_stop (qmc_dai -> qmc_chans [i ], direction );
701654 if (!ret )
702655 ret = ret_tmp ;
703656 if (ret_tmp )
704657 continue ;
705658
706- ret_tmp = qmc_chan_reset (qmc_dai -> chans [i ]. qmc_chan , direction );
659+ ret_tmp = qmc_chan_reset (qmc_dai -> qmc_chans [i ], direction );
707660 if (!ret )
708661 ret = ret_tmp ;
709662 }
@@ -715,7 +668,7 @@ static int qmc_dai_trigger(struct snd_pcm_substream *substream, int cmd,
715668 case SNDRV_PCM_TRIGGER_PAUSE_PUSH :
716669 /* Stop all QMC channels and return the first error encountered */
717670 for (i = 0 ; i < nb_chans_used ; i ++ ) {
718- ret_tmp = qmc_chan_stop (qmc_dai -> chans [i ]. qmc_chan , direction );
671+ ret_tmp = qmc_chan_stop (qmc_dai -> qmc_chans [i ], direction );
719672 if (!ret )
720673 ret = ret_tmp ;
721674 }
@@ -731,8 +684,8 @@ static int qmc_dai_trigger(struct snd_pcm_substream *substream, int cmd,
731684
732685err_stop :
733686 while (i -- ) {
734- qmc_chan_stop (qmc_dai -> chans [i ]. qmc_chan , direction );
735- qmc_chan_reset (qmc_dai -> chans [i ]. qmc_chan , direction );
687+ qmc_chan_stop (qmc_dai -> qmc_chans [i ], direction );
688+ qmc_chan_reset (qmc_dai -> qmc_chans [i ], direction );
736689 }
737690 return ret ;
738691}
@@ -791,12 +744,17 @@ static int qmc_audio_dai_parse(struct qmc_audio *qmc_audio, struct device_node *
791744 struct qmc_dai * qmc_dai ,
792745 struct snd_soc_dai_driver * qmc_soc_dai_driver )
793746{
747+ struct qmc_chan_ts_info ts_info ;
794748 struct qmc_chan_info info ;
795749 unsigned long rx_fs_rate ;
796750 unsigned long tx_fs_rate ;
751+ int prev_last_rx_ts = 0 ;
752+ int prev_last_tx_ts = 0 ;
797753 unsigned int nb_tx_ts ;
798754 unsigned int nb_rx_ts ;
799755 unsigned int i ;
756+ int last_rx_ts ;
757+ int last_tx_ts ;
800758 int count ;
801759 u32 val ;
802760 int ret ;
@@ -823,19 +781,20 @@ static int qmc_audio_dai_parse(struct qmc_audio *qmc_audio, struct device_node *
823781 return dev_err_probe (qmc_audio -> dev , - EINVAL ,
824782 "dai %d no QMC channel defined\n" , qmc_dai -> id );
825783
826- qmc_dai -> chans = devm_kcalloc (qmc_audio -> dev , count , sizeof (* qmc_dai -> chans ), GFP_KERNEL );
827- if (!qmc_dai -> chans )
784+ qmc_dai -> qmc_chans = devm_kcalloc (qmc_audio -> dev , count , sizeof (* qmc_dai -> qmc_chans ),
785+ GFP_KERNEL );
786+ if (!qmc_dai -> qmc_chans )
828787 return - ENOMEM ;
829788
830789 for (i = 0 ; i < count ; i ++ ) {
831- qmc_dai -> chans [i ]. qmc_chan = devm_qmc_chan_get_byphandles_index (qmc_audio -> dev , np ,
832- "fsl,qmc-chan" , i );
833- if (IS_ERR (qmc_dai -> chans [i ]. qmc_chan )) {
834- return dev_err_probe (qmc_audio -> dev , PTR_ERR (qmc_dai -> chans [i ]. qmc_chan ),
790+ qmc_dai -> qmc_chans [i ] = devm_qmc_chan_get_byphandles_index (qmc_audio -> dev , np ,
791+ "fsl,qmc-chan" , i );
792+ if (IS_ERR (qmc_dai -> qmc_chans [i ])) {
793+ return dev_err_probe (qmc_audio -> dev , PTR_ERR (qmc_dai -> qmc_chans [i ]),
835794 "dai %d get QMC channel %d failed\n" , qmc_dai -> id , i );
836795 }
837796
838- ret = qmc_chan_get_info (qmc_dai -> chans [i ]. qmc_chan , & info );
797+ ret = qmc_chan_get_info (qmc_dai -> qmc_chans [i ], & info );
839798 if (ret ) {
840799 dev_err (qmc_audio -> dev , "dai %d get QMC %d channel info failed %d\n" ,
841800 qmc_dai -> id , i , ret );
@@ -879,6 +838,30 @@ static int qmc_audio_dai_parse(struct qmc_audio *qmc_audio, struct device_node *
879838 return - EINVAL ;
880839 }
881840 }
841+
842+ ret = qmc_chan_get_ts_info (qmc_dai -> qmc_chans [i ], & ts_info );
843+ if (ret ) {
844+ dev_err (qmc_audio -> dev , "dai %d get QMC %d channel TS info failed %d\n" ,
845+ qmc_dai -> id , i , ret );
846+ return ret ;
847+ }
848+
849+ last_rx_ts = fls64 (ts_info .rx_ts_mask );
850+ last_tx_ts = fls64 (ts_info .tx_ts_mask );
851+
852+ if (prev_last_rx_ts > last_rx_ts ) {
853+ dev_err (qmc_audio -> dev , "dai %d QMC chan %d unordered channels (RX timeslot %d before %d)\n" ,
854+ qmc_dai -> id , i , prev_last_rx_ts , last_rx_ts );
855+ return - EINVAL ;
856+ }
857+ if (prev_last_tx_ts > last_tx_ts ) {
858+ dev_err (qmc_audio -> dev , "dai %d QMC chan %d unordered channels (TX timeslot %d before %d)\n" ,
859+ qmc_dai -> id , i , prev_last_tx_ts , last_tx_ts );
860+ return - EINVAL ;
861+ }
862+
863+ prev_last_rx_ts = last_rx_ts ;
864+ prev_last_tx_ts = last_tx_ts ;
882865 }
883866
884867 qmc_dai -> nb_chans_avail = count ;
0 commit comments