sound/soc/bcm/bcm63xx-pcm-whistler.c

Source file repositories/reference/linux-study-clean/sound/soc/bcm/bcm63xx-pcm-whistler.c

File Facts

System
Linux kernel
Corpus path
sound/soc/bcm/bcm63xx-pcm-whistler.c
Extension
.c
Size
11456 bytes
Lines
421
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

struct i2s_dma_desc {
	unsigned char *dma_area;
	dma_addr_t dma_addr;
	unsigned int dma_len;
};

struct bcm63xx_runtime_data {
	int dma_len;
	dma_addr_t dma_addr;
	dma_addr_t dma_addr_next;
};

static const struct snd_pcm_hardware bcm63xx_pcm_hardware = {
	.info = SNDRV_PCM_INFO_MMAP |
		SNDRV_PCM_INFO_MMAP_VALID |
		SNDRV_PCM_INFO_INTERLEAVED |
		SNDRV_PCM_INFO_PAUSE |
		SNDRV_PCM_INFO_RESUME,
	.formats = SNDRV_PCM_FMTBIT_S32_LE, /* support S32 only */
	.period_bytes_max = 8192 - 32,
	.periods_min = 1,
	.periods_max = PAGE_SIZE/sizeof(struct i2s_dma_desc),
	.buffer_bytes_max = 128 * 1024,
	.fifo_size = 32,
};

static int bcm63xx_pcm_hw_params(struct snd_soc_component *component,
				 struct snd_pcm_substream *substream,
				 struct snd_pcm_hw_params *params)
{
	struct i2s_dma_desc *dma_desc;
	struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);

	dma_desc = kzalloc_obj(*dma_desc, GFP_NOWAIT);
	if (!dma_desc)
		return -ENOMEM;

	snd_soc_dai_set_dma_data(snd_soc_rtd_to_cpu(rtd, 0), substream, dma_desc);

	return 0;
}

static int bcm63xx_pcm_hw_free(struct snd_soc_component *component,
			struct snd_pcm_substream *substream)
{
	struct i2s_dma_desc	*dma_desc;
	struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);

	dma_desc = snd_soc_dai_get_dma_data(snd_soc_rtd_to_cpu(rtd, 0), substream);
	kfree(dma_desc);

	return 0;
}

static int bcm63xx_pcm_trigger(struct snd_soc_component *component,
			       struct snd_pcm_substream *substream, int cmd)
{
	int ret = 0;
	struct snd_soc_pcm_runtime *rtd;
	struct bcm_i2s_priv *i2s_priv;
	struct regmap   *regmap_i2s;

	rtd = snd_soc_substream_to_rtd(substream);
	i2s_priv = dev_get_drvdata(snd_soc_rtd_to_cpu(rtd, 0)->dev);
	regmap_i2s = i2s_priv->regmap_i2s;

	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
		switch (cmd) {
		case SNDRV_PCM_TRIGGER_START:
			regmap_update_bits(regmap_i2s,
					   I2S_TX_IRQ_EN,
					   I2S_TX_DESC_OFF_INTR_EN,
					   I2S_TX_DESC_OFF_INTR_EN);
			regmap_update_bits(regmap_i2s,
					   I2S_TX_CFG,
					   I2S_TX_ENABLE_MASK,
					   I2S_TX_ENABLE);
			break;
		case SNDRV_PCM_TRIGGER_STOP:
		case SNDRV_PCM_TRIGGER_SUSPEND:
		case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
			regmap_write(regmap_i2s,
				     I2S_TX_IRQ_EN,
				     0);
			regmap_update_bits(regmap_i2s,
					   I2S_TX_CFG,
					   I2S_TX_ENABLE_MASK,
					   0);
			break;
		default:

Annotation

Implementation Notes