sound/soc/amd/acp/acp-pdm.c

Source file repositories/reference/linux-study-clean/sound/soc/amd/acp/acp-pdm.c

File Facts

System
Linux kernel
Corpus path
sound/soc/amd/acp/acp-pdm.c
Extension
.c
Size
5352 bytes
Lines
188
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.

Dependency Surface

Detected Declarations

Annotated Snippet

if (!(dma_enable & DMA_EN_MASK)) {
			writel(PDM_ENABLE, chip->base + ACP_WOV_PDM_ENABLE);
			writel(PDM_ENABLE, chip->base + ACP_WOV_PDM_DMA_ENABLE);
		}

		ret = readl_poll_timeout_atomic(chip->base + ACP_WOV_PDM_DMA_ENABLE,
						dma_enable, (dma_enable & DMA_EN_MASK),
						DELAY_US, PDM_TIMEOUT);
		break;
	case SNDRV_PCM_TRIGGER_STOP:
	case SNDRV_PCM_TRIGGER_SUSPEND:
	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
		dma_enable = readl(chip->base + ACP_WOV_PDM_DMA_ENABLE);
		if ((dma_enable & DMA_EN_MASK)) {
			writel(PDM_DISABLE, chip->base + ACP_WOV_PDM_ENABLE);
			writel(PDM_DISABLE, chip->base + ACP_WOV_PDM_DMA_ENABLE);

		}

		ret = readl_poll_timeout_atomic(chip->base + ACP_WOV_PDM_DMA_ENABLE,
						dma_enable, !(dma_enable & DMA_EN_MASK),
						DELAY_US, PDM_TIMEOUT);
		break;
	default:
		ret = -EINVAL;
		break;
	}

	return ret;
}

static int acp_dmic_hwparams(struct snd_pcm_substream *substream,
			     struct snd_pcm_hw_params *hwparams, struct snd_soc_dai *dai)
{
	struct device *dev = dai->component->dev;
	struct acp_chip_info *chip = dev_get_platdata(dev);
	unsigned int channels, ch_mask;

	channels = params_channels(hwparams);
	switch (channels) {
	case 2:
		ch_mask = 0;
		break;
	case 4:
		ch_mask = 1;
		break;
	case 6:
		ch_mask = 2;
		break;
	default:
		dev_err(dev, "Invalid channels %d\n", channels);
		return -EINVAL;
	}

	chip->ch_mask = ch_mask;
	if (params_format(hwparams) != SNDRV_PCM_FORMAT_S32_LE) {
		dev_err(dai->dev, "Invalid format:%d\n", params_format(hwparams));
		return -EINVAL;
	}

	writel(ch_mask, chip->base + ACP_WOV_PDM_NO_OF_CHANNELS);
	writel(PDM_DEC_64, chip->base + ACP_WOV_PDM_DECIMATION_FACTOR);

	return 0;
}

static int acp_dmic_dai_startup(struct snd_pcm_substream *substream,
				struct snd_soc_dai *dai)
{
	struct acp_stream *stream = substream->runtime->private_data;
	struct device *dev = dai->component->dev;
	struct acp_chip_info *chip = dev_get_platdata(dev);
	u32 ext_int_ctrl;

	stream->dai_id = DMIC_INSTANCE;
	stream->irq_bit = BIT(PDM_DMA_STAT);
	stream->pte_offset = ACP_SRAM_PDM_PTE_OFFSET;
	stream->reg_offset = ACP_REGION2_OFFSET;

	/* Enable DMIC Interrupts */
	ext_int_ctrl = readl(ACP_EXTERNAL_INTR_CNTL(chip, 0));
	ext_int_ctrl |= PDM_DMA_INTR_MASK;
	writel(ext_int_ctrl, ACP_EXTERNAL_INTR_CNTL(chip, 0));

	return 0;
}

static void acp_dmic_dai_shutdown(struct snd_pcm_substream *substream,
				  struct snd_soc_dai *dai)
{

Annotation

Implementation Notes