1 // SPDX-License-Identifier: GPL-2.0
3 // Freescale ASRC ALSA SoC Platform (DMA) driver
5 // Copyright (C) 2014 Freescale Semiconductor, Inc.
7 // Author: Nicolin Chen <nicoleotsuka@gmail.com>
9 #include <linux/dma-mapping.h>
10 #include <linux/module.h>
11 #include <linux/dma/imx-dma.h>
12 #include <sound/dmaengine_pcm.h>
13 #include <sound/pcm_params.h>
15 #include "fsl_asrc_common.h"
17 #define FSL_ASRC_DMABUF_SIZE (256 * 1024)
19 static struct snd_pcm_hardware snd_imx_hardware
= {
20 .info
= SNDRV_PCM_INFO_INTERLEAVED
|
21 SNDRV_PCM_INFO_BLOCK_TRANSFER
|
23 SNDRV_PCM_INFO_MMAP_VALID
,
24 .buffer_bytes_max
= FSL_ASRC_DMABUF_SIZE
,
25 .period_bytes_min
= 128,
26 .period_bytes_max
= 65535, /* Limited by SDMA engine */
32 static bool filter(struct dma_chan
*chan
, void *param
)
34 if (!imx_dma_is_general_purpose(chan
))
37 chan
->private = param
;
42 static void fsl_asrc_dma_complete(void *arg
)
44 struct snd_pcm_substream
*substream
= arg
;
45 struct snd_pcm_runtime
*runtime
= substream
->runtime
;
46 struct fsl_asrc_pair
*pair
= runtime
->private_data
;
48 pair
->pos
+= snd_pcm_lib_period_bytes(substream
);
49 if (pair
->pos
>= snd_pcm_lib_buffer_bytes(substream
))
52 snd_pcm_period_elapsed(substream
);
55 static int fsl_asrc_dma_prepare_and_submit(struct snd_pcm_substream
*substream
,
56 struct snd_soc_component
*component
)
58 u8 dir
= substream
->stream
== SNDRV_PCM_STREAM_PLAYBACK
? OUT
: IN
;
59 struct snd_pcm_runtime
*runtime
= substream
->runtime
;
60 struct fsl_asrc_pair
*pair
= runtime
->private_data
;
61 struct device
*dev
= component
->dev
;
62 unsigned long flags
= DMA_CTRL_ACK
;
64 /* Prepare and submit Front-End DMA channel */
65 if (!substream
->runtime
->no_period_wakeup
)
66 flags
|= DMA_PREP_INTERRUPT
;
69 pair
->desc
[!dir
] = dmaengine_prep_dma_cyclic(
70 pair
->dma_chan
[!dir
], runtime
->dma_addr
,
71 snd_pcm_lib_buffer_bytes(substream
),
72 snd_pcm_lib_period_bytes(substream
),
73 dir
== OUT
? DMA_MEM_TO_DEV
: DMA_DEV_TO_MEM
, flags
);
74 if (!pair
->desc
[!dir
]) {
75 dev_err(dev
, "failed to prepare slave DMA for Front-End\n");
79 pair
->desc
[!dir
]->callback
= fsl_asrc_dma_complete
;
80 pair
->desc
[!dir
]->callback_param
= substream
;
82 dmaengine_submit(pair
->desc
[!dir
]);
84 /* Prepare and submit Back-End DMA channel */
85 pair
->desc
[dir
] = dmaengine_prep_dma_cyclic(
86 pair
->dma_chan
[dir
], 0xffff, 64, 64, DMA_DEV_TO_DEV
, 0);
87 if (!pair
->desc
[dir
]) {
88 dev_err(dev
, "failed to prepare slave DMA for Back-End\n");
92 dmaengine_submit(pair
->desc
[dir
]);
97 static int fsl_asrc_dma_trigger(struct snd_soc_component
*component
,
98 struct snd_pcm_substream
*substream
, int cmd
)
100 struct snd_pcm_runtime
*runtime
= substream
->runtime
;
101 struct fsl_asrc_pair
*pair
= runtime
->private_data
;
105 case SNDRV_PCM_TRIGGER_START
:
106 case SNDRV_PCM_TRIGGER_RESUME
:
107 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE
:
108 ret
= fsl_asrc_dma_prepare_and_submit(substream
, component
);
111 dma_async_issue_pending(pair
->dma_chan
[IN
]);
112 dma_async_issue_pending(pair
->dma_chan
[OUT
]);
114 case SNDRV_PCM_TRIGGER_STOP
:
115 case SNDRV_PCM_TRIGGER_SUSPEND
:
116 case SNDRV_PCM_TRIGGER_PAUSE_PUSH
:
117 dmaengine_terminate_async(pair
->dma_chan
[OUT
]);
118 dmaengine_terminate_async(pair
->dma_chan
[IN
]);
127 static int fsl_asrc_dma_hw_params(struct snd_soc_component
*component
,
128 struct snd_pcm_substream
*substream
,
129 struct snd_pcm_hw_params
*params
)
131 enum dma_slave_buswidth buswidth
= DMA_SLAVE_BUSWIDTH_2_BYTES
;
132 enum sdma_peripheral_type be_peripheral_type
= IMX_DMATYPE_SSI
;
133 struct snd_soc_pcm_runtime
*rtd
= snd_soc_substream_to_rtd(substream
);
134 bool tx
= substream
->stream
== SNDRV_PCM_STREAM_PLAYBACK
;
135 struct snd_dmaengine_dai_dma_data
*dma_params_fe
= NULL
;
136 struct snd_dmaengine_dai_dma_data
*dma_params_be
= NULL
;
137 struct snd_pcm_runtime
*runtime
= substream
->runtime
;
138 struct fsl_asrc_pair
*pair
= runtime
->private_data
;
139 struct dma_chan
*tmp_chan
= NULL
, *be_chan
= NULL
;
140 struct snd_soc_component
*component_be
= NULL
;
141 struct fsl_asrc
*asrc
= pair
->asrc
;
142 struct dma_slave_config config_fe
= {}, config_be
= {};
143 struct sdma_peripheral_config audio_config
;
144 enum asrc_pair_index index
= pair
->index
;
145 struct device
*dev
= component
->dev
;
146 struct device_node
*of_dma_node
;
147 int stream
= substream
->stream
;
148 struct imx_dma_data
*tmp_data
;
149 struct snd_soc_dpcm
*dpcm
;
150 struct device
*dev_be
;
151 u8 dir
= tx
? OUT
: IN
;
155 /* Fetch the Back-End dma_data from DPCM */
156 for_each_dpcm_be(rtd
, stream
, dpcm
) {
157 struct snd_soc_pcm_runtime
*be
= dpcm
->be
;
158 struct snd_pcm_substream
*substream_be
;
159 struct snd_soc_dai
*dai
= snd_soc_rtd_to_cpu(be
, 0);
164 substream_be
= snd_soc_dpcm_get_substream(be
, stream
);
165 dma_params_be
= snd_soc_dai_get_dma_data(dai
, substream_be
);
170 if (!dma_params_be
) {
171 dev_err(dev
, "failed to get the substream of Back-End\n");
175 /* Override dma_data of the Front-End and config its dmaengine */
176 dma_params_fe
= snd_soc_dai_get_dma_data(snd_soc_rtd_to_cpu(rtd
, 0), substream
);
177 dma_params_fe
->addr
= asrc
->paddr
+ asrc
->get_fifo_addr(!dir
, index
);
178 dma_params_fe
->maxburst
= dma_params_be
->maxburst
;
180 pair
->dma_chan
[!dir
] = asrc
->get_dma_channel(pair
, !dir
);
181 if (!pair
->dma_chan
[!dir
]) {
182 dev_err(dev
, "failed to request DMA channel\n");
186 ret
= snd_dmaengine_pcm_prepare_slave_config(substream
, params
, &config_fe
);
188 dev_err(dev
, "failed to prepare DMA config for Front-End\n");
192 ret
= dmaengine_slave_config(pair
->dma_chan
[!dir
], &config_fe
);
194 dev_err(dev
, "failed to config DMA channel for Front-End\n");
198 /* Request and config DMA channel for Back-End */
200 dma_cap_set(DMA_SLAVE
, mask
);
201 dma_cap_set(DMA_CYCLIC
, mask
);
204 * The Back-End device might have already requested a DMA channel,
205 * so try to reuse it first, and then request a new one upon NULL.
207 component_be
= snd_soc_lookup_component_nolocked(dev_be
, SND_DMAENGINE_PCM_DRV_NAME
);
209 be_chan
= soc_component_to_pcm(component_be
)->chan
[substream
->stream
];
213 tmp_chan
= dma_request_chan(dev_be
, tx
? "tx" : "rx");
214 if (IS_ERR(tmp_chan
)) {
215 dev_err(dev
, "failed to request DMA channel for Back-End\n");
221 * An EDMA DEV_TO_DEV channel is fixed and bound with DMA event of each
222 * peripheral, unlike SDMA channel that is allocated dynamically. So no
223 * need to configure dma_request and dma_request2, but get dma_chan of
224 * Back-End device directly via dma_request_chan.
226 if (!asrc
->use_edma
) {
227 /* Get DMA request of Back-End */
228 tmp_data
= tmp_chan
->private;
229 pair
->dma_data
.dma_request
= tmp_data
->dma_request
;
230 be_peripheral_type
= tmp_data
->peripheral_type
;
232 dma_release_channel(tmp_chan
);
234 /* Get DMA request of Front-End */
235 tmp_chan
= asrc
->get_dma_channel(pair
, dir
);
236 tmp_data
= tmp_chan
->private;
237 pair
->dma_data
.dma_request2
= tmp_data
->dma_request
;
238 pair
->dma_data
.peripheral_type
= tmp_data
->peripheral_type
;
239 pair
->dma_data
.priority
= tmp_data
->priority
;
240 dma_release_channel(tmp_chan
);
242 of_dma_node
= pair
->dma_chan
[!dir
]->device
->dev
->of_node
;
243 pair
->dma_chan
[dir
] =
244 __dma_request_channel(&mask
, filter
, &pair
->dma_data
,
246 pair
->req_dma_chan
= true;
248 pair
->dma_chan
[dir
] = tmp_chan
;
249 /* Do not flag to release if we are reusing the Back-End one */
250 pair
->req_dma_chan
= !be_chan
;
253 if (!pair
->dma_chan
[dir
]) {
254 dev_err(dev
, "failed to request DMA channel for Back-End\n");
258 width
= snd_pcm_format_physical_width(asrc
->asrc_format
);
259 if (width
< 8 || width
> 64)
262 buswidth
= DMA_SLAVE_BUSWIDTH_1_BYTE
;
263 else if (width
== 16)
264 buswidth
= DMA_SLAVE_BUSWIDTH_2_BYTES
;
265 else if (width
== 24)
266 buswidth
= DMA_SLAVE_BUSWIDTH_3_BYTES
;
267 else if (width
<= 32)
268 buswidth
= DMA_SLAVE_BUSWIDTH_4_BYTES
;
270 buswidth
= DMA_SLAVE_BUSWIDTH_8_BYTES
;
272 config_be
.direction
= DMA_DEV_TO_DEV
;
273 config_be
.src_addr_width
= buswidth
;
274 config_be
.src_maxburst
= dma_params_be
->maxburst
;
275 config_be
.dst_addr_width
= buswidth
;
276 config_be
.dst_maxburst
= dma_params_be
->maxburst
;
278 memset(&audio_config
, 0, sizeof(audio_config
));
279 config_be
.peripheral_config
= &audio_config
;
280 config_be
.peripheral_size
= sizeof(audio_config
);
282 if (tx
&& (be_peripheral_type
== IMX_DMATYPE_SSI_DUAL
||
283 be_peripheral_type
== IMX_DMATYPE_SPDIF
))
284 audio_config
.n_fifos_dst
= 2;
285 if (!tx
&& (be_peripheral_type
== IMX_DMATYPE_SSI_DUAL
||
286 be_peripheral_type
== IMX_DMATYPE_SPDIF
))
287 audio_config
.n_fifos_src
= 2;
290 config_be
.src_addr
= asrc
->paddr
+ asrc
->get_fifo_addr(OUT
, index
);
291 config_be
.dst_addr
= dma_params_be
->addr
;
293 config_be
.dst_addr
= asrc
->paddr
+ asrc
->get_fifo_addr(IN
, index
);
294 config_be
.src_addr
= dma_params_be
->addr
;
297 ret
= dmaengine_slave_config(pair
->dma_chan
[dir
], &config_be
);
299 dev_err(dev
, "failed to config DMA channel for Back-End\n");
300 if (pair
->req_dma_chan
)
301 dma_release_channel(pair
->dma_chan
[dir
]);
308 static int fsl_asrc_dma_hw_free(struct snd_soc_component
*component
,
309 struct snd_pcm_substream
*substream
)
311 bool tx
= substream
->stream
== SNDRV_PCM_STREAM_PLAYBACK
;
312 struct snd_pcm_runtime
*runtime
= substream
->runtime
;
313 struct fsl_asrc_pair
*pair
= runtime
->private_data
;
314 u8 dir
= tx
? OUT
: IN
;
316 if (pair
->dma_chan
[!dir
])
317 dma_release_channel(pair
->dma_chan
[!dir
]);
319 /* release dev_to_dev chan if we aren't reusing the Back-End one */
320 if (pair
->dma_chan
[dir
] && pair
->req_dma_chan
)
321 dma_release_channel(pair
->dma_chan
[dir
]);
323 pair
->dma_chan
[!dir
] = NULL
;
324 pair
->dma_chan
[dir
] = NULL
;
329 static int fsl_asrc_dma_startup(struct snd_soc_component
*component
,
330 struct snd_pcm_substream
*substream
)
332 bool tx
= substream
->stream
== SNDRV_PCM_STREAM_PLAYBACK
;
333 struct snd_soc_pcm_runtime
*rtd
= snd_soc_substream_to_rtd(substream
);
334 struct snd_pcm_runtime
*runtime
= substream
->runtime
;
335 struct snd_dmaengine_dai_dma_data
*dma_data
;
336 struct device
*dev
= component
->dev
;
337 struct fsl_asrc
*asrc
= dev_get_drvdata(dev
);
338 struct fsl_asrc_pair
*pair
;
339 struct dma_chan
*tmp_chan
= NULL
;
340 u8 dir
= tx
? OUT
: IN
;
341 bool release_pair
= true;
344 ret
= snd_pcm_hw_constraint_integer(substream
->runtime
,
345 SNDRV_PCM_HW_PARAM_PERIODS
);
347 dev_err(dev
, "failed to set pcm hw params periods\n");
351 pair
= kzalloc(sizeof(*pair
) + asrc
->pair_priv_size
, GFP_KERNEL
);
356 pair
->private = (void *)pair
+ sizeof(struct fsl_asrc_pair
);
358 runtime
->private_data
= pair
;
360 /* Request a dummy pair, which will be released later.
361 * Request pair function needs channel num as input, for this
362 * dummy pair, we just request "1" channel temporarily.
364 ret
= asrc
->request_pair(1, pair
);
366 dev_err(dev
, "failed to request asrc pair\n");
370 /* Request a dummy dma channel, which will be released later. */
371 tmp_chan
= asrc
->get_dma_channel(pair
, dir
);
373 dev_err(dev
, "failed to get dma channel\n");
378 dma_data
= snd_soc_dai_get_dma_data(snd_soc_rtd_to_cpu(rtd
, 0), substream
);
380 /* Refine the snd_imx_hardware according to caps of DMA. */
381 ret
= snd_dmaengine_pcm_refine_runtime_hwparams(substream
,
386 dev_err(dev
, "failed to refine runtime hwparams\n");
390 release_pair
= false;
391 snd_soc_set_runtime_hwparams(substream
, &snd_imx_hardware
);
394 dma_release_channel(tmp_chan
);
397 asrc
->release_pair(pair
);
406 static int fsl_asrc_dma_shutdown(struct snd_soc_component
*component
,
407 struct snd_pcm_substream
*substream
)
409 struct snd_pcm_runtime
*runtime
= substream
->runtime
;
410 struct fsl_asrc_pair
*pair
= runtime
->private_data
;
411 struct fsl_asrc
*asrc
;
418 if (asrc
->pair
[pair
->index
] == pair
)
419 asrc
->pair
[pair
->index
] = NULL
;
426 static snd_pcm_uframes_t
427 fsl_asrc_dma_pcm_pointer(struct snd_soc_component
*component
,
428 struct snd_pcm_substream
*substream
)
430 struct snd_pcm_runtime
*runtime
= substream
->runtime
;
431 struct fsl_asrc_pair
*pair
= runtime
->private_data
;
433 return bytes_to_frames(substream
->runtime
, pair
->pos
);
436 static int fsl_asrc_dma_pcm_new(struct snd_soc_component
*component
,
437 struct snd_soc_pcm_runtime
*rtd
)
439 struct snd_card
*card
= rtd
->card
->snd_card
;
440 struct snd_pcm
*pcm
= rtd
->pcm
;
443 ret
= dma_coerce_mask_and_coherent(card
->dev
, DMA_BIT_MASK(32));
445 dev_err(card
->dev
, "failed to set DMA mask\n");
449 return snd_pcm_set_fixed_buffer_all(pcm
, SNDRV_DMA_TYPE_DEV
,
450 card
->dev
, FSL_ASRC_DMABUF_SIZE
);
453 struct snd_soc_component_driver fsl_asrc_component
= {
455 .hw_params
= fsl_asrc_dma_hw_params
,
456 .hw_free
= fsl_asrc_dma_hw_free
,
457 .trigger
= fsl_asrc_dma_trigger
,
458 .open
= fsl_asrc_dma_startup
,
459 .close
= fsl_asrc_dma_shutdown
,
460 .pointer
= fsl_asrc_dma_pcm_pointer
,
461 .pcm_construct
= fsl_asrc_dma_pcm_new
,
462 .legacy_dai_naming
= 1,
464 EXPORT_SYMBOL_GPL(fsl_asrc_component
);