sound/soc/bcm/cygnus-pcm.c

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

File Facts

System
Linux kernel
Corpus path
sound/soc/bcm/cygnus-pcm.c
Extension
.c
Size
21944 bytes
Lines
751
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

switch (aio->portnum) {
		case 0:
			*p_rbuf = RINGBUF_REG_PLAYBACK(0);
			break;
		case 1:
			*p_rbuf = RINGBUF_REG_PLAYBACK(2);
			break;
		case 2:
			*p_rbuf = RINGBUF_REG_PLAYBACK(4);
			break;
		case 3: /* SPDIF */
			*p_rbuf = RINGBUF_REG_PLAYBACK(6);
			break;
		default:
			status = -EINVAL;
		}
	} else {
		p_rbuf = &aio->capture_rb_regs;

		switch (aio->portnum) {
		case 0:
			*p_rbuf = RINGBUF_REG_CAPTURE(0);
			break;
		case 1:
			*p_rbuf = RINGBUF_REG_CAPTURE(2);
			break;
		case 2:
			*p_rbuf = RINGBUF_REG_CAPTURE(4);
			break;
		default:
			status = -EINVAL;
		}
	}

	return status;
}

static struct ringbuf_regs *get_ringbuf(struct snd_pcm_substream *substream)
{
	struct cygnus_aio_port *aio;
	struct ringbuf_regs *p_rbuf = NULL;

	aio = cygnus_dai_get_dma_data(substream);

	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
		p_rbuf = &aio->play_rb_regs;
	else
		p_rbuf = &aio->capture_rb_regs;

	return p_rbuf;
}

static void enable_intr(struct snd_pcm_substream *substream)
{
	struct cygnus_aio_port *aio;
	u32 clear_mask;

	aio = cygnus_dai_get_dma_data(substream);

	/* The port number maps to the bit position to be cleared */
	clear_mask = BIT(aio->portnum);

	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
		/* Clear interrupt status before enabling them */
		writel(clear_mask, aio->cygaud->audio + ESR0_STATUS_CLR_OFFSET);
		writel(clear_mask, aio->cygaud->audio + ESR1_STATUS_CLR_OFFSET);
		writel(clear_mask, aio->cygaud->audio + ESR3_STATUS_CLR_OFFSET);
		/* Unmask the interrupts of the given port*/
		writel(clear_mask, aio->cygaud->audio + ESR0_MASK_CLR_OFFSET);
		writel(clear_mask, aio->cygaud->audio + ESR1_MASK_CLR_OFFSET);
		writel(clear_mask, aio->cygaud->audio + ESR3_MASK_CLR_OFFSET);

		writel(ANY_PLAYBACK_IRQ,
			aio->cygaud->audio + INTH_R5F_MASK_CLEAR_OFFSET);
	} else {
		writel(clear_mask, aio->cygaud->audio + ESR2_STATUS_CLR_OFFSET);
		writel(clear_mask, aio->cygaud->audio + ESR4_STATUS_CLR_OFFSET);
		writel(clear_mask, aio->cygaud->audio + ESR2_MASK_CLR_OFFSET);
		writel(clear_mask, aio->cygaud->audio + ESR4_MASK_CLR_OFFSET);

		writel(ANY_CAPTURE_IRQ,
			aio->cygaud->audio + INTH_R5F_MASK_CLEAR_OFFSET);
	}

}

static void disable_intr(struct snd_pcm_substream *substream)
{
	struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
	struct cygnus_aio_port *aio;

Annotation

Implementation Notes