sound/soc/meson/axg-spdifout.c

Source file repositories/reference/linux-study-clean/sound/soc/meson/axg-spdifout.c

File Facts

System
Linux kernel
Corpus path
sound/soc/meson/axg-spdifout.c
Extension
.c
Size
12443 bytes
Lines
448
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 axg_spdifout {
	struct regmap *map;
	struct clk *mclk;
	struct clk *pclk;
};

static void axg_spdifout_enable(struct regmap *map)
{
	/* Apply both reset */
	regmap_update_bits(map, SPDIFOUT_CTRL0,
			   SPDIFOUT_CTRL0_RST_OUT | SPDIFOUT_CTRL0_RST_IN,
			   0);

	/* Clear out reset before in reset */
	regmap_update_bits(map, SPDIFOUT_CTRL0,
			   SPDIFOUT_CTRL0_RST_OUT, SPDIFOUT_CTRL0_RST_OUT);
	regmap_update_bits(map, SPDIFOUT_CTRL0,
			   SPDIFOUT_CTRL0_RST_IN,  SPDIFOUT_CTRL0_RST_IN);

	/* Enable spdifout */
	regmap_update_bits(map, SPDIFOUT_CTRL0, SPDIFOUT_CTRL0_EN,
			   SPDIFOUT_CTRL0_EN);
}

static void axg_spdifout_disable(struct regmap *map)
{
	regmap_update_bits(map, SPDIFOUT_CTRL0, SPDIFOUT_CTRL0_EN, 0);
}

static int axg_spdifout_trigger(struct snd_pcm_substream *substream, int cmd,
				struct snd_soc_dai *dai)
{
	struct axg_spdifout *priv = snd_soc_dai_get_drvdata(dai);

	switch (cmd) {
	case SNDRV_PCM_TRIGGER_START:
	case SNDRV_PCM_TRIGGER_RESUME:
	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
		axg_spdifout_enable(priv->map);
		return 0;

	case SNDRV_PCM_TRIGGER_STOP:
	case SNDRV_PCM_TRIGGER_SUSPEND:
	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
		axg_spdifout_disable(priv->map);
		return 0;

	default:
		return -EINVAL;
	}
}

static int axg_spdifout_mute(struct snd_soc_dai *dai, int mute, int direction)
{
	struct axg_spdifout *priv = snd_soc_dai_get_drvdata(dai);

	/* Use spdif valid bit to perform digital mute */
	regmap_update_bits(priv->map, SPDIFOUT_CTRL0, SPDIFOUT_CTRL0_VSET,
			   mute ? SPDIFOUT_CTRL0_VSET : 0);

	return 0;
}

static int axg_spdifout_sample_fmt(struct snd_pcm_hw_params *params,
				   struct snd_soc_dai *dai)
{
	struct axg_spdifout *priv = snd_soc_dai_get_drvdata(dai);
	unsigned int val;

	/* Set the samples spdifout will pull from the FIFO */
	switch (params_channels(params)) {
	case 1:
		val = SPDIFOUT_CTRL0_MASK(0x1);
		break;
	case 2:
		val = SPDIFOUT_CTRL0_MASK(0x3);
		break;
	default:
		dev_err(dai->dev, "too many channels for spdif dai: %u\n",
			params_channels(params));
		return -EINVAL;
	}

	regmap_update_bits(priv->map, SPDIFOUT_CTRL0,
			   SPDIFOUT_CTRL0_MASK_MASK, val);

	/* FIFO data are arranged in chunks of 64bits */
	switch (params_physical_width(params)) {
	case 8:
		/* 8 samples of 8 bits */

Annotation

Implementation Notes