sound/soc/amd/renoir/acp3x-pdm-dma.c

Source file repositories/reference/linux-study-clean/sound/soc/amd/renoir/acp3x-pdm-dma.c

File Facts

System
Linux kernel
Corpus path
sound/soc/amd/renoir/acp3x-pdm-dma.c
Extension
.c
Size
13368 bytes
Lines
507
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.

Dependency Surface

Detected Declarations

Annotated Snippet

while (++timeout < ACP_COUNTER) {
			pdm_dma_enable = rn_readl(acp_base +
						  ACP_WOV_PDM_DMA_ENABLE);
			if ((pdm_dma_enable & 0x02) == 0x00)
				break;
			udelay(DELAY_US);
		}
		if (timeout == ACP_COUNTER)
			return -ETIMEDOUT;
	}
	if (pdm_enable == ACP_PDM_ENABLE) {
		pdm_enable = ACP_PDM_DISABLE;
		rn_writel(pdm_enable, acp_base + ACP_WOV_PDM_ENABLE);
	}
	rn_writel(0x01, acp_base + ACP_WOV_PDM_FIFO_FLUSH);
	return 0;
}

static void config_acp_dma(struct pdm_stream_instance *rtd, int direction)
{
	u16 page_idx;
	u32 low, high, val;
	dma_addr_t addr;

	addr = rtd->dma_addr;
	val = 0;

	/* Group Enable */
	rn_writel(ACP_SRAM_PTE_OFFSET | BIT(31), rtd->acp_base +
		  ACPAXI2AXI_ATU_BASE_ADDR_GRP_1);
	rn_writel(PAGE_SIZE_4K_ENABLE, rtd->acp_base +
		  ACPAXI2AXI_ATU_PAGE_SIZE_GRP_1);

	for (page_idx = 0; page_idx < rtd->num_pages; page_idx++) {
		/* Load the low address of page int ACP SRAM through SRBM */
		low = lower_32_bits(addr);
		high = upper_32_bits(addr);

		rn_writel(low, rtd->acp_base + ACP_SCRATCH_REG_0 + val);
		high |= BIT(31);
		rn_writel(high, rtd->acp_base + ACP_SCRATCH_REG_0 + val + 4);
		val += 8;
		addr += PAGE_SIZE;
	}
}

static int acp_pdm_dma_open(struct snd_soc_component *component,
			    struct snd_pcm_substream *substream)
{
	struct snd_pcm_runtime *runtime;
	struct pdm_dev_data *adata;
	struct pdm_stream_instance *pdm_data;
	int ret;

	runtime = substream->runtime;
	adata = dev_get_drvdata(component->dev);
	pdm_data = kzalloc_obj(*pdm_data);
	if (!pdm_data)
		return -EINVAL;

	if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
		runtime->hw = acp_pdm_hardware_capture;

	ret = snd_pcm_hw_constraint_integer(runtime,
					    SNDRV_PCM_HW_PARAM_PERIODS);
	if (ret < 0) {
		dev_err(component->dev, "set integer constraint failed\n");
		kfree(pdm_data);
		return ret;
	}

	enable_pdm_interrupts(adata->acp_base);

	if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
		adata->capture_stream = substream;

	pdm_data->acp_base = adata->acp_base;
	runtime->private_data = pdm_data;
	return ret;
}

static int acp_pdm_dma_hw_params(struct snd_soc_component *component,
				 struct snd_pcm_substream *substream,
				 struct snd_pcm_hw_params *params)
{
	struct pdm_stream_instance *rtd;
	size_t size, period_bytes;

	rtd = substream->runtime->private_data;
	if (!rtd)

Annotation

Implementation Notes