sound/soc/fsl/fsl_asrc_m2m.c

Source file repositories/reference/linux-study-clean/sound/soc/fsl/fsl_asrc_m2m.c

File Facts

System
Linux kernel
Corpus path
sound/soc/fsl/fsl_asrc_m2m.c
Extension
.c
Size
19125 bytes
Lines
736
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 (reg32) {
			*reg32++ = reg;
		} else if (reg16) {
			*reg16++ = (u16)reg;
		} else {
			*reg24++ = (u8)reg;
			*reg24++ = (u8)(reg >> 8);
			*reg24++ = (u8)(reg >> 16);
		}
	}
	t_size += size;

	/* In case there is data left in FIFO */
	if (size)
		goto retry;
end:
	/* Update payload length */
	if (reg32)
		*length += t_size * pair->channels * 4;
	else if (reg16)
		*length += t_size * pair->channels * 2;
	else
		*length += t_size * pair->channels * 3;
}

/* config dma channel */
static int asrc_dmaconfig(struct fsl_asrc_pair *pair,
			  struct dma_chan *chan,
			  u32 dma_addr, dma_addr_t buf_addr, u32 buf_len,
			  int dir, int width)
{
	struct fsl_asrc *asrc = pair->asrc;
	struct device *dev = &asrc->pdev->dev;
	struct dma_slave_config slave_config;
	enum dma_slave_buswidth buswidth;
	unsigned int sg_len, max_period_size;
	struct scatterlist *sg;
	int ret, i;

	switch (width) {
	case 8:
		buswidth = DMA_SLAVE_BUSWIDTH_1_BYTE;
		break;
	case 16:
		buswidth = DMA_SLAVE_BUSWIDTH_2_BYTES;
		break;
	case 24:
		buswidth = DMA_SLAVE_BUSWIDTH_3_BYTES;
		break;
	case 32:
		buswidth = DMA_SLAVE_BUSWIDTH_4_BYTES;
		break;
	default:
		dev_err(dev, "invalid word width\n");
		return -EINVAL;
	}

	memset(&slave_config, 0, sizeof(slave_config));
	if (dir == IN) {
		slave_config.direction = DMA_MEM_TO_DEV;
		slave_config.dst_addr = dma_addr;
		slave_config.dst_addr_width = buswidth;
		slave_config.dst_maxburst = asrc->m2m_get_maxburst(IN, pair);
	} else {
		slave_config.direction = DMA_DEV_TO_MEM;
		slave_config.src_addr = dma_addr;
		slave_config.src_addr_width = buswidth;
		slave_config.src_maxburst = asrc->m2m_get_maxburst(OUT, pair);
	}

	ret = dmaengine_slave_config(chan, &slave_config);
	if (ret) {
		dev_err(dev, "failed to config dmaengine for %s task: %d\n",
			DIR_STR(dir), ret);
		return -EINVAL;
	}

	max_period_size = rounddown(ASRC_M2M_PERIOD_SIZE, width * pair->channels / 8);
	/* scatter gather mode */
	sg_len = buf_len / max_period_size;
	if (buf_len % max_period_size)
		sg_len += 1;

	sg = kmalloc_objs(*sg, sg_len);
	if (!sg)
		return -ENOMEM;

	sg_init_table(sg, sg_len);
	for (i = 0; i < (sg_len - 1); i++) {
		sg_dma_address(&sg[i]) = buf_addr + i * max_period_size;

Annotation

Implementation Notes