sound/soc/soc-generic-dmaengine-pcm.c
Source file repositories/reference/linux-study-clean/sound/soc/soc-generic-dmaengine-pcm.c
File Facts
- System
- Linux kernel
- Corpus path
sound/soc/soc-generic-dmaengine-pcm.c- Extension
.c- Size
- 14389 bytes
- Lines
- 506
- Domain
- Driver Families
- Bucket
- sound/soc
- Inferred role
- Driver Families: exported/initcall integration point
- Status
- integration implementation candidate
Why This File Exists
Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.
- Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.
- Exports symbols or registers init work; inspect boot/module ordering and who consumes the exported contract.
- Allocates kernel memory; connect allocation flags and lifetime to context constraints.
- Defines or uses C structs; map object ownership, embedded links, reference counts, and lock ownership.
Dependency Surface
linux/module.hlinux/init.hlinux/dmaengine.hlinux/slab.hsound/pcm.hsound/pcm_params.hsound/soc.hlinux/dma-mapping.hlinux/of.hsound/dmaengine_pcm.h
Detected Declarations
function snd_dmaengine_pcm_prepare_slave_configfunction dmaengine_pcm_hw_paramsfunction dmaengine_pcm_set_runtime_hwparamsfunction dmaengine_pcm_openfunction dmaengine_pcm_closefunction dmaengine_pcm_triggerfunction dmaengine_pcm_can_report_residuefunction dmaengine_pcm_newfunction for_each_pcm_streamsfunction dmaengine_pcm_pointerfunction dmaengine_copyfunction dmaengine_pcm_sync_stopfunction dmaengine_pcm_request_chan_offunction for_each_pcm_streamsfunction dmaengine_pcm_release_chanfunction for_each_pcm_streamsfunction snd_dmaengine_pcm_registerfunction snd_dmaengine_pcm_unregisterexport snd_dmaengine_pcm_prepare_slave_configexport snd_dmaengine_pcm_registerexport snd_dmaengine_pcm_unregister
Annotated Snippet
if (!pcm->chan[i] && (pcm->flags & SND_DMAENGINE_PCM_FLAG_COMPAT)) {
pcm->chan[i] = dmaengine_pcm_compat_request_channel(
component, rtd, substream);
}
if (!pcm->chan[i]) {
dev_err(component->dev,
"Missing dma channel for stream: %d\n", i);
return -EINVAL;
}
snd_pcm_set_managed_buffer(substream,
SNDRV_DMA_TYPE_DEV_IRAM,
dmaengine_dma_dev(pcm, substream),
prealloc_buffer_size,
max_buffer_size);
if (!dmaengine_pcm_can_report_residue(dev, pcm->chan[i]))
pcm->flags |= SND_DMAENGINE_PCM_FLAG_NO_RESIDUE;
if (rtd->pcm->streams[i].pcm->name[0] == '\0') {
strscpy_pad(rtd->pcm->streams[i].pcm->name,
rtd->pcm->streams[i].pcm->id,
sizeof(rtd->pcm->streams[i].pcm->name));
}
}
return 0;
}
static snd_pcm_uframes_t dmaengine_pcm_pointer(
struct snd_soc_component *component,
struct snd_pcm_substream *substream)
{
struct dmaengine_pcm *pcm = soc_component_to_pcm(component);
if (pcm->flags & SND_DMAENGINE_PCM_FLAG_NO_RESIDUE)
return snd_dmaengine_pcm_pointer_no_residue(substream);
else
return snd_dmaengine_pcm_pointer(substream);
}
static int dmaengine_copy(struct snd_soc_component *component,
struct snd_pcm_substream *substream,
int channel, unsigned long hwoff,
struct iov_iter *iter, unsigned long bytes)
{
struct snd_pcm_runtime *runtime = substream->runtime;
struct dmaengine_pcm *pcm = soc_component_to_pcm(component);
int (*process)(struct snd_pcm_substream *substream,
int channel, unsigned long hwoff,
unsigned long bytes) = pcm->config->process;
bool is_playback = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
void *dma_ptr = runtime->dma_area + hwoff +
channel * (runtime->dma_bytes / runtime->channels);
if (is_playback)
if (copy_from_iter(dma_ptr, bytes, iter) != bytes)
return -EFAULT;
if (process) {
int ret = process(substream, channel, hwoff, bytes);
if (ret < 0)
return ret;
}
if (!is_playback)
if (copy_to_iter(dma_ptr, bytes, iter) != bytes)
return -EFAULT;
return 0;
}
static int dmaengine_pcm_sync_stop(struct snd_soc_component *component,
struct snd_pcm_substream *substream)
{
return snd_dmaengine_pcm_sync_stop(substream);
}
static const struct snd_soc_component_driver dmaengine_pcm_component = {
.name = SND_DMAENGINE_PCM_DRV_NAME,
.probe_order = SND_SOC_COMP_ORDER_LATE,
.open = dmaengine_pcm_open,
.close = dmaengine_pcm_close,
.hw_params = dmaengine_pcm_hw_params,
.trigger = dmaengine_pcm_trigger,
.pointer = dmaengine_pcm_pointer,
.pcm_new = dmaengine_pcm_new,
.sync_stop = dmaengine_pcm_sync_stop,
.debugfs_prefix = "dma",
Annotation
- Immediate include surface: `linux/module.h`, `linux/init.h`, `linux/dmaengine.h`, `linux/slab.h`, `sound/pcm.h`, `sound/pcm_params.h`, `sound/soc.h`, `linux/dma-mapping.h`.
- Detected declarations: `function snd_dmaengine_pcm_prepare_slave_config`, `function dmaengine_pcm_hw_params`, `function dmaengine_pcm_set_runtime_hwparams`, `function dmaengine_pcm_open`, `function dmaengine_pcm_close`, `function dmaengine_pcm_trigger`, `function dmaengine_pcm_can_report_residue`, `function dmaengine_pcm_new`, `function for_each_pcm_streams`, `function dmaengine_pcm_pointer`.
- Atlas domain: Driver Families / sound/soc.
- Implementation status: integration implementation candidate.
Implementation Notes
- This generated page is the file-by-file coverage layer; curated subsystem chapters should link here when they synthesize a multi-file control flow.
- Core OS pages should be promoted from atlas-only to deep-reviewed when they explain data structures, invariants, locking, lifecycle, and C implementation snippets.
- Driver-family pages are intentionally pattern-oriented unless they are part of the selected PCIe/NVMe representative device path.