1 // SPDX-License-Identifier: GPL-2.0+
3 // Copyright (C) 2013, Analog Devices Inc.
4 // Author: Lars-Peter Clausen <lars@metafoo.de>
6 #include <linux/module.h>
7 #include <linux/init.h>
8 #include <linux/dmaengine.h>
9 #include <linux/slab.h>
10 #include <sound/pcm.h>
11 #include <sound/pcm_params.h>
12 #include <sound/soc.h>
13 #include <linux/dma-mapping.h>
16 #include <sound/dmaengine_pcm.h>
19 * The platforms dmaengine driver does not support reporting the amount of
20 * bytes that are still left to transfer.
22 #define SND_DMAENGINE_PCM_FLAG_NO_RESIDUE BIT(31)
24 struct dmaengine_pcm
{
25 struct dma_chan
*chan
[SNDRV_PCM_STREAM_LAST
+ 1];
26 const struct snd_dmaengine_pcm_config
*config
;
27 struct snd_soc_component component
;
31 static struct dmaengine_pcm
*soc_component_to_pcm(struct snd_soc_component
*p
)
33 return container_of(p
, struct dmaengine_pcm
, component
);
36 static struct device
*dmaengine_dma_dev(struct dmaengine_pcm
*pcm
,
37 struct snd_pcm_substream
*substream
)
39 if (!pcm
->chan
[substream
->stream
])
42 return pcm
->chan
[substream
->stream
]->device
->dev
;
46 * snd_dmaengine_pcm_prepare_slave_config() - Generic prepare_slave_config callback
47 * @substream: PCM substream
49 * @slave_config: DMA slave config to prepare
51 * This function can be used as a generic prepare_slave_config callback for
52 * platforms which make use of the snd_dmaengine_dai_dma_data struct for their
53 * DAI DMA data. Internally the function will first call
54 * snd_hwparams_to_dma_slave_config to fill in the slave config based on the
55 * hw_params, followed by snd_dmaengine_set_config_from_dai_data to fill in the
56 * remaining fields based on the DAI DMA data.
58 int snd_dmaengine_pcm_prepare_slave_config(struct snd_pcm_substream
*substream
,
59 struct snd_pcm_hw_params
*params
, struct dma_slave_config
*slave_config
)
61 struct snd_soc_pcm_runtime
*rtd
= substream
->private_data
;
62 struct snd_dmaengine_dai_dma_data
*dma_data
;
65 dma_data
= snd_soc_dai_get_dma_data(rtd
->cpu_dai
, substream
);
67 ret
= snd_hwparams_to_dma_slave_config(substream
, params
, slave_config
);
71 snd_dmaengine_pcm_set_config_from_dai_data(substream
, dma_data
,
76 EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_prepare_slave_config
);
78 static int dmaengine_pcm_hw_params(struct snd_pcm_substream
*substream
,
79 struct snd_pcm_hw_params
*params
)
81 struct snd_soc_pcm_runtime
*rtd
= substream
->private_data
;
82 struct snd_soc_component
*component
=
83 snd_soc_rtdcom_lookup(rtd
, SND_DMAENGINE_PCM_DRV_NAME
);
84 struct dmaengine_pcm
*pcm
= soc_component_to_pcm(component
);
85 struct dma_chan
*chan
= snd_dmaengine_pcm_get_chan(substream
);
86 int (*prepare_slave_config
)(struct snd_pcm_substream
*substream
,
87 struct snd_pcm_hw_params
*params
,
88 struct dma_slave_config
*slave_config
);
89 struct dma_slave_config slave_config
;
92 memset(&slave_config
, 0, sizeof(slave_config
));
95 prepare_slave_config
= snd_dmaengine_pcm_prepare_slave_config
;
97 prepare_slave_config
= pcm
->config
->prepare_slave_config
;
99 if (prepare_slave_config
) {
100 ret
= prepare_slave_config(substream
, params
, &slave_config
);
104 ret
= dmaengine_slave_config(chan
, &slave_config
);
109 return snd_pcm_lib_malloc_pages(substream
, params_buffer_bytes(params
));
112 static int dmaengine_pcm_set_runtime_hwparams(struct snd_pcm_substream
*substream
)
114 struct snd_soc_pcm_runtime
*rtd
= substream
->private_data
;
115 struct snd_soc_component
*component
=
116 snd_soc_rtdcom_lookup(rtd
, SND_DMAENGINE_PCM_DRV_NAME
);
117 struct dmaengine_pcm
*pcm
= soc_component_to_pcm(component
);
118 struct device
*dma_dev
= dmaengine_dma_dev(pcm
, substream
);
119 struct dma_chan
*chan
= pcm
->chan
[substream
->stream
];
120 struct snd_dmaengine_dai_dma_data
*dma_data
;
121 struct dma_slave_caps dma_caps
;
122 struct snd_pcm_hardware hw
;
123 u32 addr_widths
= BIT(DMA_SLAVE_BUSWIDTH_1_BYTE
) |
124 BIT(DMA_SLAVE_BUSWIDTH_2_BYTES
) |
125 BIT(DMA_SLAVE_BUSWIDTH_4_BYTES
);
129 if (pcm
->config
&& pcm
->config
->pcm_hardware
)
130 return snd_soc_set_runtime_hwparams(substream
,
131 pcm
->config
->pcm_hardware
);
133 dma_data
= snd_soc_dai_get_dma_data(rtd
->cpu_dai
, substream
);
135 memset(&hw
, 0, sizeof(hw
));
136 hw
.info
= SNDRV_PCM_INFO_MMAP
| SNDRV_PCM_INFO_MMAP_VALID
|
137 SNDRV_PCM_INFO_INTERLEAVED
;
139 hw
.periods_max
= UINT_MAX
;
140 hw
.period_bytes_min
= 256;
141 hw
.period_bytes_max
= dma_get_max_seg_size(dma_dev
);
142 hw
.buffer_bytes_max
= SIZE_MAX
;
143 hw
.fifo_size
= dma_data
->fifo_size
;
145 if (pcm
->flags
& SND_DMAENGINE_PCM_FLAG_NO_RESIDUE
)
146 hw
.info
|= SNDRV_PCM_INFO_BATCH
;
148 ret
= dma_get_slave_caps(chan
, &dma_caps
);
150 if (dma_caps
.cmd_pause
&& dma_caps
.cmd_resume
)
151 hw
.info
|= SNDRV_PCM_INFO_PAUSE
| SNDRV_PCM_INFO_RESUME
;
152 if (dma_caps
.residue_granularity
<= DMA_RESIDUE_GRANULARITY_SEGMENT
)
153 hw
.info
|= SNDRV_PCM_INFO_BATCH
;
155 if (substream
->stream
== SNDRV_PCM_STREAM_PLAYBACK
)
156 addr_widths
= dma_caps
.dst_addr_widths
;
158 addr_widths
= dma_caps
.src_addr_widths
;
162 * If SND_DMAENGINE_PCM_DAI_FLAG_PACK is set keep
163 * hw.formats set to 0, meaning no restrictions are in place.
164 * In this case it's the responsibility of the DAI driver to
165 * provide the supported format information.
167 if (!(dma_data
->flags
& SND_DMAENGINE_PCM_DAI_FLAG_PACK
))
169 * Prepare formats mask for valid/allowed sample types. If the
170 * dma does not have support for the given physical word size,
171 * it needs to be masked out so user space can not use the
172 * format which produces corrupted audio.
173 * In case the dma driver does not implement the slave_caps the
174 * default assumption is that it supports 1, 2 and 4 bytes
177 for (i
= SNDRV_PCM_FORMAT_FIRST
; i
<= SNDRV_PCM_FORMAT_LAST
; i
++) {
178 int bits
= snd_pcm_format_physical_width(i
);
181 * Enable only samples with DMA supported physical
190 if (addr_widths
& (1 << (bits
/ 8)))
191 hw
.formats
|= pcm_format_to_bits(i
);
194 /* Unsupported types */
199 return snd_soc_set_runtime_hwparams(substream
, &hw
);
202 static int dmaengine_pcm_open(struct snd_pcm_substream
*substream
)
204 struct snd_soc_pcm_runtime
*rtd
= substream
->private_data
;
205 struct snd_soc_component
*component
=
206 snd_soc_rtdcom_lookup(rtd
, SND_DMAENGINE_PCM_DRV_NAME
);
207 struct dmaengine_pcm
*pcm
= soc_component_to_pcm(component
);
208 struct dma_chan
*chan
= pcm
->chan
[substream
->stream
];
211 ret
= dmaengine_pcm_set_runtime_hwparams(substream
);
215 return snd_dmaengine_pcm_open(substream
, chan
);
218 static struct dma_chan
*dmaengine_pcm_compat_request_channel(
219 struct snd_soc_pcm_runtime
*rtd
,
220 struct snd_pcm_substream
*substream
)
222 struct snd_soc_component
*component
=
223 snd_soc_rtdcom_lookup(rtd
, SND_DMAENGINE_PCM_DRV_NAME
);
224 struct dmaengine_pcm
*pcm
= soc_component_to_pcm(component
);
225 struct snd_dmaengine_dai_dma_data
*dma_data
;
226 dma_filter_fn fn
= NULL
;
228 dma_data
= snd_soc_dai_get_dma_data(rtd
->cpu_dai
, substream
);
230 if ((pcm
->flags
& SND_DMAENGINE_PCM_FLAG_HALF_DUPLEX
) && pcm
->chan
[0])
233 if (pcm
->config
&& pcm
->config
->compat_request_channel
)
234 return pcm
->config
->compat_request_channel(rtd
, substream
);
237 fn
= pcm
->config
->compat_filter_fn
;
239 return snd_dmaengine_pcm_request_channel(fn
, dma_data
->filter_data
);
242 static bool dmaengine_pcm_can_report_residue(struct device
*dev
,
243 struct dma_chan
*chan
)
245 struct dma_slave_caps dma_caps
;
248 ret
= dma_get_slave_caps(chan
, &dma_caps
);
250 dev_warn(dev
, "Failed to get DMA channel capabilities, falling back to period counting: %d\n",
255 if (dma_caps
.residue_granularity
== DMA_RESIDUE_GRANULARITY_DESCRIPTOR
)
261 static int dmaengine_pcm_new(struct snd_soc_pcm_runtime
*rtd
)
263 struct snd_soc_component
*component
=
264 snd_soc_rtdcom_lookup(rtd
, SND_DMAENGINE_PCM_DRV_NAME
);
265 struct dmaengine_pcm
*pcm
= soc_component_to_pcm(component
);
266 const struct snd_dmaengine_pcm_config
*config
= pcm
->config
;
267 struct device
*dev
= component
->dev
;
268 struct snd_dmaengine_dai_dma_data
*dma_data
;
269 struct snd_pcm_substream
*substream
;
270 size_t prealloc_buffer_size
;
271 size_t max_buffer_size
;
275 if (config
&& config
->prealloc_buffer_size
) {
276 prealloc_buffer_size
= config
->prealloc_buffer_size
;
277 max_buffer_size
= config
->pcm_hardware
->buffer_bytes_max
;
279 prealloc_buffer_size
= 512 * 1024;
280 max_buffer_size
= SIZE_MAX
;
283 for (i
= SNDRV_PCM_STREAM_PLAYBACK
; i
<= SNDRV_PCM_STREAM_CAPTURE
; i
++) {
284 substream
= rtd
->pcm
->streams
[i
].substream
;
288 dma_data
= snd_soc_dai_get_dma_data(rtd
->cpu_dai
, substream
);
291 (pcm
->flags
& SND_DMAENGINE_PCM_FLAG_CUSTOM_CHANNEL_NAME
))
292 pcm
->chan
[i
] = dma_request_slave_channel(dev
,
293 dma_data
->chan_name
);
295 if (!pcm
->chan
[i
] && (pcm
->flags
& SND_DMAENGINE_PCM_FLAG_COMPAT
)) {
296 pcm
->chan
[i
] = dmaengine_pcm_compat_request_channel(rtd
,
301 dev_err(component
->dev
,
302 "Missing dma channel for stream: %d\n", i
);
306 ret
= snd_pcm_lib_preallocate_pages(substream
,
307 SNDRV_DMA_TYPE_DEV_IRAM
,
308 dmaengine_dma_dev(pcm
, substream
),
309 prealloc_buffer_size
,
314 if (!dmaengine_pcm_can_report_residue(dev
, pcm
->chan
[i
]))
315 pcm
->flags
|= SND_DMAENGINE_PCM_FLAG_NO_RESIDUE
;
321 static snd_pcm_uframes_t
dmaengine_pcm_pointer(
322 struct snd_pcm_substream
*substream
)
324 struct snd_soc_pcm_runtime
*rtd
= substream
->private_data
;
325 struct snd_soc_component
*component
=
326 snd_soc_rtdcom_lookup(rtd
, SND_DMAENGINE_PCM_DRV_NAME
);
327 struct dmaengine_pcm
*pcm
= soc_component_to_pcm(component
);
329 if (pcm
->flags
& SND_DMAENGINE_PCM_FLAG_NO_RESIDUE
)
330 return snd_dmaengine_pcm_pointer_no_residue(substream
);
332 return snd_dmaengine_pcm_pointer(substream
);
335 static int dmaengine_copy_user(struct snd_pcm_substream
*substream
,
336 int channel
, unsigned long hwoff
,
337 void __user
*buf
, unsigned long bytes
)
339 struct snd_soc_pcm_runtime
*rtd
= substream
->private_data
;
340 struct snd_soc_component
*component
=
341 snd_soc_rtdcom_lookup(rtd
, SND_DMAENGINE_PCM_DRV_NAME
);
342 struct snd_pcm_runtime
*runtime
= substream
->runtime
;
343 struct dmaengine_pcm
*pcm
= soc_component_to_pcm(component
);
344 int (*process
)(struct snd_pcm_substream
*substream
,
345 int channel
, unsigned long hwoff
,
346 void *buf
, unsigned long bytes
) = pcm
->config
->process
;
347 bool is_playback
= substream
->stream
== SNDRV_PCM_STREAM_PLAYBACK
;
348 void *dma_ptr
= runtime
->dma_area
+ hwoff
+
349 channel
* (runtime
->dma_bytes
/ runtime
->channels
);
353 if (copy_from_user(dma_ptr
, buf
, bytes
))
357 ret
= process(substream
, channel
, hwoff
, (__force
void *)buf
, bytes
);
363 if (copy_to_user(buf
, dma_ptr
, bytes
))
369 static const struct snd_pcm_ops dmaengine_pcm_ops
= {
370 .open
= dmaengine_pcm_open
,
371 .close
= snd_dmaengine_pcm_close
,
372 .ioctl
= snd_pcm_lib_ioctl
,
373 .hw_params
= dmaengine_pcm_hw_params
,
374 .hw_free
= snd_pcm_lib_free_pages
,
375 .trigger
= snd_dmaengine_pcm_trigger
,
376 .pointer
= dmaengine_pcm_pointer
,
379 static const struct snd_pcm_ops dmaengine_pcm_process_ops
= {
380 .open
= dmaengine_pcm_open
,
381 .close
= snd_dmaengine_pcm_close
,
382 .ioctl
= snd_pcm_lib_ioctl
,
383 .hw_params
= dmaengine_pcm_hw_params
,
384 .hw_free
= snd_pcm_lib_free_pages
,
385 .trigger
= snd_dmaengine_pcm_trigger
,
386 .pointer
= dmaengine_pcm_pointer
,
387 .copy_user
= dmaengine_copy_user
,
390 static const struct snd_soc_component_driver dmaengine_pcm_component
= {
391 .name
= SND_DMAENGINE_PCM_DRV_NAME
,
392 .probe_order
= SND_SOC_COMP_ORDER_LATE
,
393 .ops
= &dmaengine_pcm_ops
,
394 .pcm_new
= dmaengine_pcm_new
,
397 static const struct snd_soc_component_driver dmaengine_pcm_component_process
= {
398 .name
= SND_DMAENGINE_PCM_DRV_NAME
,
399 .probe_order
= SND_SOC_COMP_ORDER_LATE
,
400 .ops
= &dmaengine_pcm_process_ops
,
401 .pcm_new
= dmaengine_pcm_new
,
404 static const char * const dmaengine_pcm_dma_channel_names
[] = {
405 [SNDRV_PCM_STREAM_PLAYBACK
] = "tx",
406 [SNDRV_PCM_STREAM_CAPTURE
] = "rx",
409 static int dmaengine_pcm_request_chan_of(struct dmaengine_pcm
*pcm
,
410 struct device
*dev
, const struct snd_dmaengine_pcm_config
*config
)
414 struct dma_chan
*chan
;
416 if ((pcm
->flags
& (SND_DMAENGINE_PCM_FLAG_NO_DT
|
417 SND_DMAENGINE_PCM_FLAG_CUSTOM_CHANNEL_NAME
)) ||
421 if (config
&& config
->dma_dev
) {
423 * If this warning is seen, it probably means that your Linux
424 * device structure does not match your HW device structure.
425 * It would be best to refactor the Linux device structure to
426 * correctly match the HW structure.
428 dev_warn(dev
, "DMA channels sourced from device %s",
429 dev_name(config
->dma_dev
));
430 dev
= config
->dma_dev
;
433 for (i
= SNDRV_PCM_STREAM_PLAYBACK
; i
<= SNDRV_PCM_STREAM_CAPTURE
;
435 if (pcm
->flags
& SND_DMAENGINE_PCM_FLAG_HALF_DUPLEX
)
438 name
= dmaengine_pcm_dma_channel_names
[i
];
439 if (config
&& config
->chan_names
[i
])
440 name
= config
->chan_names
[i
];
441 chan
= dma_request_slave_channel_reason(dev
, name
);
443 if (PTR_ERR(chan
) == -EPROBE_DEFER
)
444 return -EPROBE_DEFER
;
449 if (pcm
->flags
& SND_DMAENGINE_PCM_FLAG_HALF_DUPLEX
)
453 if (pcm
->flags
& SND_DMAENGINE_PCM_FLAG_HALF_DUPLEX
)
454 pcm
->chan
[1] = pcm
->chan
[0];
459 static void dmaengine_pcm_release_chan(struct dmaengine_pcm
*pcm
)
463 for (i
= SNDRV_PCM_STREAM_PLAYBACK
; i
<= SNDRV_PCM_STREAM_CAPTURE
;
467 dma_release_channel(pcm
->chan
[i
]);
468 if (pcm
->flags
& SND_DMAENGINE_PCM_FLAG_HALF_DUPLEX
)
474 * snd_dmaengine_pcm_register - Register a dmaengine based PCM device
475 * @dev: The parent device for the PCM device
476 * @config: Platform specific PCM configuration
477 * @flags: Platform specific quirks
479 int snd_dmaengine_pcm_register(struct device
*dev
,
480 const struct snd_dmaengine_pcm_config
*config
, unsigned int flags
)
482 struct dmaengine_pcm
*pcm
;
485 pcm
= kzalloc(sizeof(*pcm
), GFP_KERNEL
);
489 #ifdef CONFIG_DEBUG_FS
490 pcm
->component
.debugfs_prefix
= "dma";
492 pcm
->config
= config
;
495 ret
= dmaengine_pcm_request_chan_of(pcm
, dev
, config
);
499 if (config
&& config
->process
)
500 ret
= snd_soc_add_component(dev
, &pcm
->component
,
501 &dmaengine_pcm_component_process
,
504 ret
= snd_soc_add_component(dev
, &pcm
->component
,
505 &dmaengine_pcm_component
, NULL
, 0);
512 dmaengine_pcm_release_chan(pcm
);
516 EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_register
);
519 * snd_dmaengine_pcm_unregister - Removes a dmaengine based PCM device
520 * @dev: Parent device the PCM was register with
522 * Removes a dmaengine based PCM device previously registered with
523 * snd_dmaengine_pcm_register.
525 void snd_dmaengine_pcm_unregister(struct device
*dev
)
527 struct snd_soc_component
*component
;
528 struct dmaengine_pcm
*pcm
;
530 component
= snd_soc_lookup_component(dev
, SND_DMAENGINE_PCM_DRV_NAME
);
534 pcm
= soc_component_to_pcm(component
);
536 snd_soc_unregister_component(dev
);
537 dmaengine_pcm_release_chan(pcm
);
540 EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_unregister
);
542 MODULE_LICENSE("GPL");