drivers/gpu/drm/xlnx/zynqmp_dp_audio.c

Source file repositories/reference/linux-study-clean/drivers/gpu/drm/xlnx/zynqmp_dp_audio.c

File Facts

System
Linux kernel
Corpus path
drivers/gpu/drm/xlnx/zynqmp_dp_audio.c
Extension
.c
Size
11297 bytes
Lines
449
Domain
Driver Families
Bucket
drivers/gpu
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 zynqmp_dpsub_audio {
	void __iomem *base;

	struct snd_soc_card card;

	const char *dai_name;
	const char *link_names[ZYNQMP_NUM_PCMS];
	const char *pcm_names[ZYNQMP_NUM_PCMS];

	struct snd_soc_dai_driver dai_driver;
	struct snd_dmaengine_pcm_config pcm_configs[2];

	struct snd_soc_dai_link links[ZYNQMP_NUM_PCMS];

	struct {
		struct snd_soc_dai_link_component cpu;
		struct snd_soc_dai_link_component platform;
	} components[ZYNQMP_NUM_PCMS];

	/*
	 * Protects:
	 * - enabled_streams
	 * - volumes
	 * - current_rate
	 */
	struct mutex enable_lock;

	u32 enabled_streams;
	u32 current_rate;

	u16 volumes[2];
};

static const struct snd_pcm_hardware zynqmp_dp_pcm_hw = {
	.info = SNDRV_PCM_INFO_MMAP |
		SNDRV_PCM_INFO_MMAP_VALID |
		SNDRV_PCM_INFO_INTERLEAVED |
		SNDRV_PCM_INFO_PAUSE |
		SNDRV_PCM_INFO_RESUME |
		SNDRV_PCM_INFO_NO_PERIOD_WAKEUP,

	.buffer_bytes_max       = 128 * 1024,
	.period_bytes_min       = 256,
	.period_bytes_max       = 1024 * 1024,
	.periods_min            = 2,
	.periods_max            = 256,
};

static int zynqmp_dp_startup(struct snd_pcm_substream *substream)
{
	struct snd_pcm_runtime *runtime = substream->runtime;

	snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES,
				   256);

	return 0;
}

static const struct snd_soc_ops zynqmp_dp_ops = {
	.startup = zynqmp_dp_startup,
};

static void zynqmp_dp_audio_write(struct zynqmp_dpsub_audio *audio, int reg,
				  u32 val)
{
	writel(val, audio->base + reg);
}

static int dp_dai_hw_params(struct snd_pcm_substream *substream,
			    struct snd_pcm_hw_params *params,
			    struct snd_soc_dai *socdai)
{
	struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
	struct zynqmp_dpsub *dpsub =
		snd_soc_dai_get_drvdata(snd_soc_rtd_to_cpu(rtd, 0));
	struct zynqmp_dpsub_audio *audio = dpsub->audio;
	int ret;
	u32 sample_rate;
	struct snd_aes_iec958 iec = { 0 };
	unsigned long rate;

	sample_rate = params_rate(params);

	if (sample_rate != 48000 && sample_rate != 44100)
		return -EINVAL;

	guard(mutex)(&audio->enable_lock);

	if (audio->enabled_streams && audio->current_rate != sample_rate) {
		dev_err(dpsub->dev,

Annotation

Implementation Notes