hc
2024-10-22 8ac6c7a54ed1b98d142dce24b11c6de6a1e239a5
kernel/sound/core/pcm_dmaengine.c
....@@ -1,3 +1,4 @@
1
+// SPDX-License-Identifier: GPL-2.0-or-later
12 /*
23 * Copyright (C) 2012, Analog Devices Inc.
34 * Author: Lars-Peter Clausen <lars@metafoo.de>
....@@ -7,16 +8,6 @@
78 * mxs-pcm.c, Copyright (C) 2011 Freescale Semiconductor, Inc.
89 * ep93xx-pcm.c, Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.org>
910 * Copyright (C) 2006 Applied Data Systems
10
- *
11
- * This program is free software; you can redistribute it and/or modify it
12
- * under the terms of the GNU General Public License as published by the
13
- * Free Software Foundation; either version 2 of the License, or (at your
14
- * option) any later version.
15
- *
16
- * You should have received a copy of the GNU General Public License along
17
- * with this program; if not, write to the Free Software Foundation, Inc.,
18
- * 675 Mass Ave, Cambridge, MA 02139, USA.
19
- *
2011 */
2112 #include <linux/module.h>
2213 #include <linux/init.h>
....@@ -135,11 +126,14 @@
135126 }
136127
137128 slave_config->slave_id = dma_data->slave_id;
129
+ slave_config->peripheral_config = dma_data->peripheral_config;
130
+ slave_config->peripheral_size = dma_data->peripheral_size;
138131 }
139132 EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_set_config_from_dai_data);
140133
141134 static void dmaengine_pcm_dma_complete(void *arg)
142135 {
136
+ unsigned int new_pos;
143137 struct snd_pcm_substream *substream = arg;
144138 struct dmaengine_pcm_runtime_data *prtd;
145139
....@@ -151,9 +145,10 @@
151145
152146 prtd = substream_to_prtd(substream);
153147
154
- prtd->pos += snd_pcm_lib_period_bytes(substream);
155
- if (prtd->pos >= snd_pcm_lib_buffer_bytes(substream))
156
- prtd->pos = 0;
148
+ new_pos = prtd->pos + snd_pcm_lib_period_bytes(substream);
149
+ if (new_pos >= snd_pcm_lib_buffer_bytes(substream))
150
+ new_pos = 0;
151
+ prtd->pos = new_pos;
157152 snd_pcm_stream_unlock_irq(substream);
158153
159154 snd_pcm_period_elapsed(substream);
....@@ -259,6 +254,7 @@
259254 snd_pcm_uframes_t snd_dmaengine_pcm_pointer(struct snd_pcm_substream *substream)
260255 {
261256 struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream);
257
+ struct snd_pcm_runtime *runtime = substream->runtime;
262258 struct dma_tx_state state;
263259 unsigned int buf_size;
264260 unsigned int pos = 0;
....@@ -268,7 +264,10 @@
268264 if (state.residue > 0 && state.residue <= buf_size)
269265 pos = buf_size - state.residue;
270266
271
- return bytes_to_frames(substream->runtime, pos);
267
+ runtime->delay = bytes_to_frames(runtime,
268
+ state.in_flight_bytes);
269
+
270
+ return bytes_to_frames(runtime, pos);
272271 }
273272 EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_pointer);
274273
....@@ -368,7 +367,8 @@
368367 EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_close);
369368
370369 /**
371
- * snd_dmaengine_pcm_release_chan_close - Close a dmaengine based PCM substream and release channel
370
+ * snd_dmaengine_pcm_close_release_chan - Close a dmaengine based PCM
371
+ * substream and release channel
372372 * @substream: PCM substream
373373 *
374374 * Releases the DMA channel associated with the PCM substream.
....@@ -385,4 +385,87 @@
385385 }
386386 EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_close_release_chan);
387387
388
+/**
389
+ * snd_dmaengine_pcm_refine_runtime_hwparams - Refine runtime hw params
390
+ * @substream: PCM substream
391
+ * @dma_data: DAI DMA data
392
+ * @hw: PCM hw params
393
+ * @chan: DMA channel to use for data transfers
394
+ *
395
+ * Returns 0 on success, a negative error code otherwise.
396
+ *
397
+ * This function will query DMA capability, then refine the pcm hardware
398
+ * parameters.
399
+ */
400
+int snd_dmaengine_pcm_refine_runtime_hwparams(
401
+ struct snd_pcm_substream *substream,
402
+ struct snd_dmaengine_dai_dma_data *dma_data,
403
+ struct snd_pcm_hardware *hw,
404
+ struct dma_chan *chan)
405
+{
406
+ struct dma_slave_caps dma_caps;
407
+ u32 addr_widths = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) |
408
+ BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) |
409
+ BIT(DMA_SLAVE_BUSWIDTH_4_BYTES);
410
+ snd_pcm_format_t i;
411
+ int ret = 0;
412
+
413
+ if (!hw || !chan || !dma_data)
414
+ return -EINVAL;
415
+
416
+ ret = dma_get_slave_caps(chan, &dma_caps);
417
+ if (ret == 0) {
418
+ if (dma_caps.cmd_pause && dma_caps.cmd_resume)
419
+ hw->info |= SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME;
420
+ if (dma_caps.residue_granularity <= DMA_RESIDUE_GRANULARITY_SEGMENT)
421
+ hw->info |= SNDRV_PCM_INFO_BATCH;
422
+
423
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
424
+ addr_widths = dma_caps.dst_addr_widths;
425
+ else
426
+ addr_widths = dma_caps.src_addr_widths;
427
+ }
428
+
429
+ /*
430
+ * If SND_DMAENGINE_PCM_DAI_FLAG_PACK is set keep
431
+ * hw.formats set to 0, meaning no restrictions are in place.
432
+ * In this case it's the responsibility of the DAI driver to
433
+ * provide the supported format information.
434
+ */
435
+ if (!(dma_data->flags & SND_DMAENGINE_PCM_DAI_FLAG_PACK))
436
+ /*
437
+ * Prepare formats mask for valid/allowed sample types. If the
438
+ * dma does not have support for the given physical word size,
439
+ * it needs to be masked out so user space can not use the
440
+ * format which produces corrupted audio.
441
+ * In case the dma driver does not implement the slave_caps the
442
+ * default assumption is that it supports 1, 2 and 4 bytes
443
+ * widths.
444
+ */
445
+ pcm_for_each_format(i) {
446
+ int bits = snd_pcm_format_physical_width(i);
447
+
448
+ /*
449
+ * Enable only samples with DMA supported physical
450
+ * widths
451
+ */
452
+ switch (bits) {
453
+ case 8:
454
+ case 16:
455
+ case 24:
456
+ case 32:
457
+ case 64:
458
+ if (addr_widths & (1 << (bits / 8)))
459
+ hw->formats |= pcm_format_to_bits(i);
460
+ break;
461
+ default:
462
+ /* Unsupported types */
463
+ break;
464
+ }
465
+ }
466
+
467
+ return ret;
468
+}
469
+EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_refine_runtime_hwparams);
470
+
388471 MODULE_LICENSE("GPL");