sound/soc/amd/ps/ps-sdw-dma.c

Source file repositories/reference/linux-study-clean/sound/soc/amd/ps/ps-sdw-dma.c

File Facts

System
Linux kernel
Corpus path
sound/soc/amd/ps/ps-sdw-dma.c
Extension
.c
Size
27881 bytes
Lines
805
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 (manager_instance) {
		case ACP_SDW0:
			reg_dma_size = acp63_sdw0_dma_reg[stream_id].reg_dma_size;
			reg_fifo_addr =	acp63_sdw0_dma_reg[stream_id].reg_fifo_addr;
			reg_fifo_size = acp63_sdw0_dma_reg[stream_id].reg_fifo_size;
			reg_ring_buf_size = acp63_sdw0_dma_reg[stream_id].reg_ring_buf_size;
			reg_ring_buf_addr = acp63_sdw0_dma_reg[stream_id].reg_ring_buf_addr;
			break;
		case ACP_SDW1:
			reg_dma_size = acp63_sdw1_dma_reg[stream_id].reg_dma_size;
			reg_fifo_addr =	acp63_sdw1_dma_reg[stream_id].reg_fifo_addr;
			reg_fifo_size = acp63_sdw1_dma_reg[stream_id].reg_fifo_size;
			reg_ring_buf_size = acp63_sdw1_dma_reg[stream_id].reg_ring_buf_size;
			reg_ring_buf_addr = acp63_sdw1_dma_reg[stream_id].reg_ring_buf_addr;
			break;
		default:
			return -EINVAL;
		}
		break;
	case ACP70_PCI_REV:
	case ACP71_PCI_REV:
	case ACP72_PCI_REV:
		switch (manager_instance) {
		case ACP_SDW0:
			reg_dma_size = acp70_sdw0_dma_reg[stream_id].reg_dma_size;
			reg_fifo_addr =	acp70_sdw0_dma_reg[stream_id].reg_fifo_addr;
			reg_fifo_size = acp70_sdw0_dma_reg[stream_id].reg_fifo_size;
			reg_ring_buf_size = acp70_sdw0_dma_reg[stream_id].reg_ring_buf_size;
			reg_ring_buf_addr = acp70_sdw0_dma_reg[stream_id].reg_ring_buf_addr;
			break;
		case ACP_SDW1:
			reg_dma_size = acp70_sdw1_dma_reg[stream_id].reg_dma_size;
			reg_fifo_addr =	acp70_sdw1_dma_reg[stream_id].reg_fifo_addr;
			reg_fifo_size = acp70_sdw1_dma_reg[stream_id].reg_fifo_size;
			reg_ring_buf_size = acp70_sdw1_dma_reg[stream_id].reg_ring_buf_size;
			reg_ring_buf_addr = acp70_sdw1_dma_reg[stream_id].reg_ring_buf_addr;
			break;
		default:
			return -EINVAL;
		}
		break;
	default:
		return -EINVAL;
	}
	sdw_fifo_offset = ACP_SDW_FIFO_OFFSET(manager_instance);
	sdw_mem_window_offset = SDW_MEM_WINDOW_START(manager_instance);
	sdw_fifo_addr = sdw_fifo_offset + (stream_id * SDW_FIFO_OFFSET);
	sdw_ring_buf_addr = sdw_mem_window_offset + (stream_id * ACP_SDW_RING_BUFF_ADDR_OFFSET);
	sdw_ring_buf_size = size;
	writel(sdw_ring_buf_size, acp_base + reg_ring_buf_size);
	writel(sdw_ring_buf_addr, acp_base + reg_ring_buf_addr);
	writel(sdw_fifo_addr, acp_base + reg_fifo_addr);
	writel(SDW_DMA_SIZE, acp_base + reg_dma_size);
	writel(SDW_FIFO_SIZE, acp_base + reg_fifo_size);
	return 0;
}

static int acp63_sdw_dma_open(struct snd_soc_component *component,
			      struct snd_pcm_substream *substream)
{
	struct snd_pcm_runtime *runtime;
	struct acp_sdw_dma_stream *stream;
	struct snd_soc_dai *cpu_dai;
	struct amd_sdw_manager *amd_manager;
	struct snd_soc_pcm_runtime *prtd = snd_soc_substream_to_rtd(substream);
	int ret;

	runtime = substream->runtime;
	cpu_dai = snd_soc_rtd_to_cpu(prtd, 0);
	amd_manager = snd_soc_dai_get_drvdata(cpu_dai);
	stream = kzalloc_obj(*stream);
	if (!stream)
		return -ENOMEM;

	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
		runtime->hw = acp63_sdw_hardware_playback;
	else
		runtime->hw = acp63_sdw_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(stream);
		return ret;
	}

	stream->stream_id = cpu_dai->id;
	stream->instance = amd_manager->instance;
	runtime->private_data = stream;
	return ret;

Annotation

Implementation Notes