sound/soc/adi/axi-spdif.c

Source file repositories/reference/linux-study-clean/sound/soc/adi/axi-spdif.c

File Facts

System
Linux kernel
Corpus path
sound/soc/adi/axi-spdif.c
Extension
.c
Size
6352 bytes
Lines
268
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 axi_spdif {
	struct regmap *regmap;
	struct clk *clk;
	struct clk *clk_ref;

	struct snd_dmaengine_dai_dma_data dma_data;

	struct snd_ratnum ratnum;
	struct snd_pcm_hw_constraint_ratnums rate_constraints;
};

static int axi_spdif_trigger(struct snd_pcm_substream *substream, int cmd,
	struct snd_soc_dai *dai)
{
	struct axi_spdif *spdif = snd_soc_dai_get_drvdata(dai);
	unsigned int val;

	switch (cmd) {
	case SNDRV_PCM_TRIGGER_START:
	case SNDRV_PCM_TRIGGER_RESUME:
	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
		val = AXI_SPDIF_CTRL_TXDATA;
		break;
	case SNDRV_PCM_TRIGGER_STOP:
	case SNDRV_PCM_TRIGGER_SUSPEND:
	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
		val = 0;
		break;
	default:
		return -EINVAL;
	}

	regmap_update_bits(spdif->regmap, AXI_SPDIF_REG_CTRL,
		AXI_SPDIF_CTRL_TXDATA, val);

	return 0;
}

static int axi_spdif_hw_params(struct snd_pcm_substream *substream,
	struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
{
	struct axi_spdif *spdif = snd_soc_dai_get_drvdata(dai);
	unsigned int rate = params_rate(params);
	unsigned int clkdiv, stat;

	switch (params_rate(params)) {
	case 32000:
		stat = AXI_SPDIF_FREQ_32000;
		break;
	case 44100:
		stat = AXI_SPDIF_FREQ_44100;
		break;
	case 48000:
		stat = AXI_SPDIF_FREQ_48000;
		break;
	default:
		stat = AXI_SPDIF_FREQ_NA;
		break;
	}

	clkdiv = DIV_ROUND_CLOSEST(clk_get_rate(spdif->clk_ref),
			rate * 64 * 2) - 1;
	clkdiv <<= AXI_SPDIF_CTRL_CLKDIV_OFFSET;

	regmap_write(spdif->regmap, AXI_SPDIF_REG_STAT, stat);
	regmap_update_bits(spdif->regmap, AXI_SPDIF_REG_CTRL,
		AXI_SPDIF_CTRL_CLKDIV_MASK, clkdiv);

	return 0;
}

static int axi_spdif_dai_probe(struct snd_soc_dai *dai)
{
	struct axi_spdif *spdif = snd_soc_dai_get_drvdata(dai);

	snd_soc_dai_init_dma_data(dai, &spdif->dma_data, NULL);

	return 0;
}

static int axi_spdif_startup(struct snd_pcm_substream *substream,
	struct snd_soc_dai *dai)
{
	struct axi_spdif *spdif = snd_soc_dai_get_drvdata(dai);
	int ret;

	ret = snd_pcm_hw_constraint_ratnums(substream->runtime, 0,
			   SNDRV_PCM_HW_PARAM_RATE,
			   &spdif->rate_constraints);
	if (ret)

Annotation

Implementation Notes