sound/soc/stm/stm32_spdifrx.c
Source file repositories/reference/linux-study-clean/sound/soc/stm/stm32_spdifrx.c
File Facts
- System
- Linux kernel
- Corpus path
sound/soc/stm/stm32_spdifrx.c- Extension
.c- Size
- 29498 bytes
- Lines
- 1070
- Domain
- Driver Families
- Bucket
- sound/soc
- Inferred role
- Driver Families: implementation source
- Status
- source 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.
- Uses kernel synchronization; read lock ordering, sleepability, and interrupt context assumptions before translating.
- Touches IRQ or DMA behavior; this matters for the representative real-device path.
- 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/bitfield.hlinux/clk.hlinux/completion.hlinux/delay.hlinux/module.hlinux/of_platform.hlinux/pm_runtime.hlinux/regmap.hlinux/reset.hsound/dmaengine_pcm.hsound/pcm_params.h
Detected Declarations
struct stm32_spdifrx_datafunction stm32_spdifrx_dma_completefunction stm32_spdifrx_dma_ctrl_startfunction stm32_spdifrx_dma_ctrl_stopfunction stm32_spdifrx_start_syncfunction stm32_spdifrx_stopfunction stm32_spdifrx_dma_ctrl_registerfunction stm32_spdifrx_infofunction stm32_spdifrx_ub_infofunction stm32_spdifrx_get_ctrl_datafunction stm32_spdifrx_capture_getfunction stm32_spdif_user_bits_getfunction stm32_spdifrx_dai_register_ctrlsfunction stm32_spdifrx_dai_probefunction stm32_spdifrx_readable_regfunction stm32_spdifrx_volatile_regfunction stm32_spdifrx_writeable_regfunction stm32_spdifrx_isrfunction scoped_guardfunction scoped_guardfunction stm32_spdifrx_startupfunction stm32_spdifrx_hw_paramsfunction stm32_spdifrx_triggerfunction stm32_spdifrx_shutdownfunction stm32_spdifrx_parse_offunction stm32_spdifrx_removefunction stm32_spdifrx_probefunction stm32_spdifrx_suspendfunction stm32_spdifrx_resume
Annotated Snippet
struct stm32_spdifrx_data {
struct platform_device *pdev;
void __iomem *base;
struct regmap *regmap;
const struct regmap_config *regmap_conf;
struct completion cs_completion;
struct clk *kclk;
struct snd_dmaengine_dai_dma_data dma_params;
struct snd_pcm_substream *substream;
struct snd_dma_buffer *dmab;
struct dma_chan *ctrl_chan;
struct dma_async_tx_descriptor *desc;
struct dma_slave_config slave_config;
dma_addr_t phys_addr;
spinlock_t lock; /* Sync enabling lock */
spinlock_t irq_lock; /* Prevent race condition on stream state */
unsigned char cs[SPDIFRX_CS_BYTES_NB];
unsigned char ub[SPDIFRX_UB_BYTES_NB];
int irq;
int refcount;
};
static void stm32_spdifrx_dma_complete(void *data)
{
struct stm32_spdifrx_data *spdifrx = (struct stm32_spdifrx_data *)data;
struct platform_device *pdev = spdifrx->pdev;
u32 *p_start = (u32 *)spdifrx->dmab->area;
u32 *p_end = p_start + (2 * SPDIFRX_CS_BYTES_NB) - 1;
u32 *ptr = p_start;
u16 *ub_ptr = (short *)spdifrx->ub;
int i = 0;
regmap_update_bits(spdifrx->regmap, STM32_SPDIFRX_CR,
SPDIFRX_CR_CBDMAEN,
(unsigned int)~SPDIFRX_CR_CBDMAEN);
if (!spdifrx->dmab->area)
return;
while (ptr <= p_end) {
if (*ptr & SPDIFRX_CSR_SOB)
break;
ptr++;
}
if (ptr > p_end) {
dev_err(&pdev->dev, "Start of S/PDIF block not found\n");
return;
}
while (i < SPDIFRX_CS_BYTES_NB) {
spdifrx->cs[i] = (unsigned char)SPDIFRX_CSR_CSGET(*ptr);
*ub_ptr++ = SPDIFRX_CSR_USRGET(*ptr++);
if (ptr > p_end) {
dev_err(&pdev->dev, "Failed to get channel status\n");
return;
}
i++;
}
complete(&spdifrx->cs_completion);
}
static int stm32_spdifrx_dma_ctrl_start(struct stm32_spdifrx_data *spdifrx)
{
dma_cookie_t cookie;
int err;
spdifrx->desc = dmaengine_prep_slave_single(spdifrx->ctrl_chan,
spdifrx->dmab->addr,
SPDIFRX_CSR_BUF_LENGTH,
DMA_DEV_TO_MEM,
DMA_CTRL_ACK);
if (!spdifrx->desc)
return -EINVAL;
spdifrx->desc->callback = stm32_spdifrx_dma_complete;
spdifrx->desc->callback_param = spdifrx;
cookie = dmaengine_submit(spdifrx->desc);
err = dma_submit_error(cookie);
if (err)
return -EINVAL;
dma_async_issue_pending(spdifrx->ctrl_chan);
return 0;
}
static void stm32_spdifrx_dma_ctrl_stop(struct stm32_spdifrx_data *spdifrx)
{
Annotation
- Immediate include surface: `linux/bitfield.h`, `linux/clk.h`, `linux/completion.h`, `linux/delay.h`, `linux/module.h`, `linux/of_platform.h`, `linux/pm_runtime.h`, `linux/regmap.h`.
- Detected declarations: `struct stm32_spdifrx_data`, `function stm32_spdifrx_dma_complete`, `function stm32_spdifrx_dma_ctrl_start`, `function stm32_spdifrx_dma_ctrl_stop`, `function stm32_spdifrx_start_sync`, `function stm32_spdifrx_stop`, `function stm32_spdifrx_dma_ctrl_register`, `function stm32_spdifrx_info`, `function stm32_spdifrx_ub_info`, `function stm32_spdifrx_get_ctrl_data`.
- Atlas domain: Driver Families / sound/soc.
- Implementation status: source implementation candidate.
- Synchronization appears in or near this file; preserve lock ordering, sleepability, and interrupt-context constraints.
- IRQ or DMA behavior appears here, which is relevant to the selected PCIe/NVMe device path.
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.