sound/soc/stm/stm32_adfsdm.c

Source file repositories/reference/linux-study-clean/sound/soc/stm/stm32_adfsdm.c

File Facts

System
Linux kernel
Corpus path
sound/soc/stm/stm32_adfsdm.c
Extension
.c
Size
10715 bytes
Lines
395
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 stm32_adfsdm_priv {
	struct snd_soc_dai_driver dai_drv;
	struct snd_pcm_substream *substream;
	struct device *dev;

	/* IIO */
	struct iio_channel *iio_ch;
	struct iio_cb_buffer *iio_cb;
	bool iio_active;

	/* PCM buffer */
	unsigned char *pcm_buff;
	unsigned int pos;

	struct mutex lock; /* protect against race condition on iio state */
};

static const struct snd_pcm_hardware stm32_adfsdm_pcm_hw = {
	.info = SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER |
		SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_PAUSE,
	.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE,

	.channels_min = 1,
	.channels_max = 1,

	.periods_min = 2,
	.periods_max = DFSDM_MAX_PERIODS,

	.period_bytes_max = DFSDM_MAX_PERIOD_SIZE,
	.buffer_bytes_max = DFSDM_MAX_PERIODS * DFSDM_MAX_PERIOD_SIZE
};

static void stm32_adfsdm_shutdown(struct snd_pcm_substream *substream,
				  struct snd_soc_dai *dai)
{
	struct stm32_adfsdm_priv *priv = snd_soc_dai_get_drvdata(dai);

	guard(mutex)(&priv->lock);
	if (priv->iio_active) {
		iio_channel_stop_all_cb(priv->iio_cb);
		priv->iio_active = false;
	}
}

static int stm32_adfsdm_dai_prepare(struct snd_pcm_substream *substream,
				    struct snd_soc_dai *dai)
{
	struct stm32_adfsdm_priv *priv = snd_soc_dai_get_drvdata(dai);
	int ret;

	guard(mutex)(&priv->lock);
	if (priv->iio_active) {
		iio_channel_stop_all_cb(priv->iio_cb);
		priv->iio_active = false;
	}

	ret = iio_write_channel_attribute(priv->iio_ch,
					  substream->runtime->rate, 0,
					  IIO_CHAN_INFO_SAMP_FREQ);
	if (ret < 0) {
		dev_err(dai->dev, "%s: Failed to set %d sampling rate\n",
			__func__, substream->runtime->rate);
		return ret;
	}

	if (!priv->iio_active) {
		ret = iio_channel_start_all_cb(priv->iio_cb);
		if (!ret)
			priv->iio_active = true;
		else
			dev_err(dai->dev, "%s: IIO channel start failed (%d)\n",
				__func__, ret);
	}

	return ret;
}

static int stm32_adfsdm_set_sysclk(struct snd_soc_dai *dai, int clk_id,
				   unsigned int freq, int dir)
{
	struct stm32_adfsdm_priv *priv = snd_soc_dai_get_drvdata(dai);
	ssize_t size;
	char str_freq[10];

	dev_dbg(dai->dev, "%s: Enter for freq %d\n", __func__, freq);

	/* Set IIO frequency if CODEC is master as clock comes from SPI_IN */

	snprintf(str_freq, sizeof(str_freq), "%u\n", freq);
	size = iio_write_channel_ext_info(priv->iio_ch, "spi_clk_freq",

Annotation

Implementation Notes