@@ -135,14 +135,15 @@ static int fsl_asrc_dma_hw_params(struct snd_soc_component *component,
135135 struct snd_dmaengine_dai_dma_data * dma_params_be = NULL ;
136136 struct snd_pcm_runtime * runtime = substream -> runtime ;
137137 struct fsl_asrc_pair * pair = runtime -> private_data ;
138+ struct dma_chan * tmp_chan = NULL , * be_chan = NULL ;
139+ struct snd_soc_component * component_be = NULL ;
138140 struct fsl_asrc * asrc = pair -> asrc ;
139141 struct dma_slave_config config_fe , config_be ;
140142 enum asrc_pair_index index = pair -> index ;
141143 struct device * dev = component -> dev ;
142144 int stream = substream -> stream ;
143145 struct imx_dma_data * tmp_data ;
144146 struct snd_soc_dpcm * dpcm ;
145- struct dma_chan * tmp_chan ;
146147 struct device * dev_be ;
147148 u8 dir = tx ? OUT : IN ;
148149 dma_cap_mask_t mask ;
@@ -197,18 +198,30 @@ static int fsl_asrc_dma_hw_params(struct snd_soc_component *component,
197198 dma_cap_set (DMA_SLAVE , mask );
198199 dma_cap_set (DMA_CYCLIC , mask );
199200
201+ /*
202+ * The Back-End device might have already requested a DMA channel,
203+ * so try to reuse it first, and then request a new one upon NULL.
204+ */
205+ component_be = snd_soc_lookup_component_nolocked (dev_be , SND_DMAENGINE_PCM_DRV_NAME );
206+ if (component_be ) {
207+ be_chan = soc_component_to_pcm (component_be )-> chan [substream -> stream ];
208+ tmp_chan = be_chan ;
209+ }
210+ if (!tmp_chan )
211+ tmp_chan = dma_request_slave_channel (dev_be , tx ? "tx" : "rx" );
212+
200213 /*
201214 * An EDMA DEV_TO_DEV channel is fixed and bound with DMA event of each
202215 * peripheral, unlike SDMA channel that is allocated dynamically. So no
203- * need to configure dma_request and dma_request2, but get dma_chan via
204- * dma_request_slave_channel directly with dma name of Front -End device
216+ * need to configure dma_request and dma_request2, but get dma_chan of
217+ * Back -End device directly via dma_request_slave_channel.
205218 */
206219 if (!asrc -> use_edma ) {
207220 /* Get DMA request of Back-End */
208- tmp_chan = dma_request_slave_channel (dev_be , tx ? "tx" : "rx" );
209221 tmp_data = tmp_chan -> private ;
210222 pair -> dma_data .dma_request = tmp_data -> dma_request ;
211- dma_release_channel (tmp_chan );
223+ if (!be_chan )
224+ dma_release_channel (tmp_chan );
212225
213226 /* Get DMA request of Front-End */
214227 tmp_chan = asrc -> get_dma_channel (pair , dir );
@@ -220,9 +233,11 @@ static int fsl_asrc_dma_hw_params(struct snd_soc_component *component,
220233
221234 pair -> dma_chan [dir ] =
222235 dma_request_channel (mask , filter , & pair -> dma_data );
236+ pair -> req_dma_chan = true;
223237 } else {
224- pair -> dma_chan [dir ] =
225- asrc -> get_dma_channel (pair , dir );
238+ pair -> dma_chan [dir ] = tmp_chan ;
239+ /* Do not flag to release if we are reusing the Back-End one */
240+ pair -> req_dma_chan = !be_chan ;
226241 }
227242
228243 if (!pair -> dma_chan [dir ]) {
@@ -261,7 +276,8 @@ static int fsl_asrc_dma_hw_params(struct snd_soc_component *component,
261276 ret = dmaengine_slave_config (pair -> dma_chan [dir ], & config_be );
262277 if (ret ) {
263278 dev_err (dev , "failed to config DMA channel for Back-End\n" );
264- dma_release_channel (pair -> dma_chan [dir ]);
279+ if (pair -> req_dma_chan )
280+ dma_release_channel (pair -> dma_chan [dir ]);
265281 return ret ;
266282 }
267283
@@ -273,19 +289,22 @@ static int fsl_asrc_dma_hw_params(struct snd_soc_component *component,
273289static int fsl_asrc_dma_hw_free (struct snd_soc_component * component ,
274290 struct snd_pcm_substream * substream )
275291{
292+ bool tx = substream -> stream == SNDRV_PCM_STREAM_PLAYBACK ;
276293 struct snd_pcm_runtime * runtime = substream -> runtime ;
277294 struct fsl_asrc_pair * pair = runtime -> private_data ;
295+ u8 dir = tx ? OUT : IN ;
278296
279297 snd_pcm_set_runtime_buffer (substream , NULL );
280298
281- if (pair -> dma_chan [IN ])
282- dma_release_channel (pair -> dma_chan [IN ]);
299+ if (pair -> dma_chan [! dir ])
300+ dma_release_channel (pair -> dma_chan [! dir ]);
283301
284- if (pair -> dma_chan [OUT ])
285- dma_release_channel (pair -> dma_chan [OUT ]);
302+ /* release dev_to_dev chan if we aren't reusing the Back-End one */
303+ if (pair -> dma_chan [dir ] && pair -> req_dma_chan )
304+ dma_release_channel (pair -> dma_chan [dir ]);
286305
287- pair -> dma_chan [IN ] = NULL ;
288- pair -> dma_chan [OUT ] = NULL ;
306+ pair -> dma_chan [! dir ] = NULL ;
307+ pair -> dma_chan [dir ] = NULL ;
289308
290309 return 0 ;
291310}
0 commit comments