155da0948SArnaud Pouliquen // SPDX-License-Identifier: GPL-2.0 255da0948SArnaud Pouliquen /* 355da0948SArnaud Pouliquen * This file is part of STM32 DFSDM ASoC DAI driver 455da0948SArnaud Pouliquen * 555da0948SArnaud Pouliquen * Copyright (C) 2017, STMicroelectronics - All Rights Reserved 655da0948SArnaud Pouliquen * Authors: Arnaud Pouliquen <arnaud.pouliquen@st.com> 755da0948SArnaud Pouliquen * Olivier Moysan <olivier.moysan@st.com> 855da0948SArnaud Pouliquen */ 955da0948SArnaud Pouliquen 1055da0948SArnaud Pouliquen #include <linux/clk.h> 1155da0948SArnaud Pouliquen #include <linux/module.h> 1219441e35SOlivier Moysan #include <linux/mutex.h> 1355da0948SArnaud Pouliquen #include <linux/platform_device.h> 1455da0948SArnaud Pouliquen #include <linux/slab.h> 1555da0948SArnaud Pouliquen 1655da0948SArnaud Pouliquen #include <linux/iio/iio.h> 1755da0948SArnaud Pouliquen #include <linux/iio/consumer.h> 1855da0948SArnaud Pouliquen #include <linux/iio/adc/stm32-dfsdm-adc.h> 1955da0948SArnaud Pouliquen 2055da0948SArnaud Pouliquen #include <sound/pcm.h> 2155da0948SArnaud Pouliquen #include <sound/soc.h> 2255da0948SArnaud Pouliquen 2355da0948SArnaud Pouliquen #define STM32_ADFSDM_DRV_NAME "stm32-adfsdm" 2455da0948SArnaud Pouliquen 2555da0948SArnaud Pouliquen #define DFSDM_MAX_PERIOD_SIZE (PAGE_SIZE / 2) 2655da0948SArnaud Pouliquen #define DFSDM_MAX_PERIODS 6 2755da0948SArnaud Pouliquen 2855da0948SArnaud Pouliquen struct stm32_adfsdm_priv { 2955da0948SArnaud Pouliquen struct snd_soc_dai_driver dai_drv; 3055da0948SArnaud Pouliquen struct snd_pcm_substream *substream; 3155da0948SArnaud Pouliquen struct device *dev; 3255da0948SArnaud Pouliquen 3355da0948SArnaud Pouliquen /* IIO */ 3455da0948SArnaud Pouliquen struct iio_channel *iio_ch; 3555da0948SArnaud Pouliquen struct iio_cb_buffer *iio_cb; 3655da0948SArnaud Pouliquen bool iio_active; 3755da0948SArnaud Pouliquen 3855da0948SArnaud Pouliquen /* PCM buffer */ 3955da0948SArnaud Pouliquen unsigned char *pcm_buff; 4055da0948SArnaud Pouliquen unsigned int pos; 4119441e35SOlivier Moysan 4219441e35SOlivier Moysan struct mutex lock; /* protect against race condition on iio state */ 4355da0948SArnaud Pouliquen }; 4455da0948SArnaud Pouliquen 4555da0948SArnaud Pouliquen static const struct snd_pcm_hardware stm32_adfsdm_pcm_hw = { 4655da0948SArnaud Pouliquen .info = SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER | 47d151cf89SOlivier Moysan SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_PAUSE, 481e7f6e1cSOlivier Moysan .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE, 4955da0948SArnaud Pouliquen 5055da0948SArnaud Pouliquen .channels_min = 1, 5155da0948SArnaud Pouliquen .channels_max = 1, 5255da0948SArnaud Pouliquen 5355da0948SArnaud Pouliquen .periods_min = 2, 5455da0948SArnaud Pouliquen .periods_max = DFSDM_MAX_PERIODS, 5555da0948SArnaud Pouliquen 5655da0948SArnaud Pouliquen .period_bytes_max = DFSDM_MAX_PERIOD_SIZE, 5755da0948SArnaud Pouliquen .buffer_bytes_max = DFSDM_MAX_PERIODS * DFSDM_MAX_PERIOD_SIZE 5855da0948SArnaud Pouliquen }; 5955da0948SArnaud Pouliquen 6055da0948SArnaud Pouliquen static void stm32_adfsdm_shutdown(struct snd_pcm_substream *substream, 6155da0948SArnaud Pouliquen struct snd_soc_dai *dai) 6255da0948SArnaud Pouliquen { 6355da0948SArnaud Pouliquen struct stm32_adfsdm_priv *priv = snd_soc_dai_get_drvdata(dai); 6455da0948SArnaud Pouliquen 6519441e35SOlivier Moysan mutex_lock(&priv->lock); 6655da0948SArnaud Pouliquen if (priv->iio_active) { 6755da0948SArnaud Pouliquen iio_channel_stop_all_cb(priv->iio_cb); 6855da0948SArnaud Pouliquen priv->iio_active = false; 6955da0948SArnaud Pouliquen } 7019441e35SOlivier Moysan mutex_unlock(&priv->lock); 7155da0948SArnaud Pouliquen } 7255da0948SArnaud Pouliquen 7355da0948SArnaud Pouliquen static int stm32_adfsdm_dai_prepare(struct snd_pcm_substream *substream, 7455da0948SArnaud Pouliquen struct snd_soc_dai *dai) 7555da0948SArnaud Pouliquen { 7655da0948SArnaud Pouliquen struct stm32_adfsdm_priv *priv = snd_soc_dai_get_drvdata(dai); 7755da0948SArnaud Pouliquen int ret; 7855da0948SArnaud Pouliquen 7919441e35SOlivier Moysan mutex_lock(&priv->lock); 8019441e35SOlivier Moysan if (priv->iio_active) { 8119441e35SOlivier Moysan iio_channel_stop_all_cb(priv->iio_cb); 8219441e35SOlivier Moysan priv->iio_active = false; 8319441e35SOlivier Moysan } 8419441e35SOlivier Moysan 8555da0948SArnaud Pouliquen ret = iio_write_channel_attribute(priv->iio_ch, 8655da0948SArnaud Pouliquen substream->runtime->rate, 0, 8755da0948SArnaud Pouliquen IIO_CHAN_INFO_SAMP_FREQ); 8855da0948SArnaud Pouliquen if (ret < 0) { 8955da0948SArnaud Pouliquen dev_err(dai->dev, "%s: Failed to set %d sampling rate\n", 9055da0948SArnaud Pouliquen __func__, substream->runtime->rate); 9119441e35SOlivier Moysan goto out; 9255da0948SArnaud Pouliquen } 9355da0948SArnaud Pouliquen 9455da0948SArnaud Pouliquen if (!priv->iio_active) { 9555da0948SArnaud Pouliquen ret = iio_channel_start_all_cb(priv->iio_cb); 9655da0948SArnaud Pouliquen if (!ret) 9755da0948SArnaud Pouliquen priv->iio_active = true; 9855da0948SArnaud Pouliquen else 9955da0948SArnaud Pouliquen dev_err(dai->dev, "%s: IIO channel start failed (%d)\n", 10055da0948SArnaud Pouliquen __func__, ret); 10155da0948SArnaud Pouliquen } 10255da0948SArnaud Pouliquen 10319441e35SOlivier Moysan out: 10419441e35SOlivier Moysan mutex_unlock(&priv->lock); 10519441e35SOlivier Moysan 10655da0948SArnaud Pouliquen return ret; 10755da0948SArnaud Pouliquen } 10855da0948SArnaud Pouliquen 10955da0948SArnaud Pouliquen static int stm32_adfsdm_set_sysclk(struct snd_soc_dai *dai, int clk_id, 11055da0948SArnaud Pouliquen unsigned int freq, int dir) 11155da0948SArnaud Pouliquen { 11255da0948SArnaud Pouliquen struct stm32_adfsdm_priv *priv = snd_soc_dai_get_drvdata(dai); 11355da0948SArnaud Pouliquen ssize_t size; 11455da0948SArnaud Pouliquen char str_freq[10]; 11555da0948SArnaud Pouliquen 11655da0948SArnaud Pouliquen dev_dbg(dai->dev, "%s: Enter for freq %d\n", __func__, freq); 11755da0948SArnaud Pouliquen 11855da0948SArnaud Pouliquen /* Set IIO frequency if CODEC is master as clock comes from SPI_IN */ 11955da0948SArnaud Pouliquen 120*11033e51SPierre-Louis Bossart snprintf(str_freq, sizeof(str_freq), "%u\n", freq); 12155da0948SArnaud Pouliquen size = iio_write_channel_ext_info(priv->iio_ch, "spi_clk_freq", 12255da0948SArnaud Pouliquen str_freq, sizeof(str_freq)); 12355da0948SArnaud Pouliquen if (size != sizeof(str_freq)) { 12455da0948SArnaud Pouliquen dev_err(dai->dev, "%s: Failed to set SPI clock\n", 12555da0948SArnaud Pouliquen __func__); 12655da0948SArnaud Pouliquen return -EINVAL; 12755da0948SArnaud Pouliquen } 12855da0948SArnaud Pouliquen return 0; 12955da0948SArnaud Pouliquen } 13055da0948SArnaud Pouliquen 13155da0948SArnaud Pouliquen static const struct snd_soc_dai_ops stm32_adfsdm_dai_ops = { 13255da0948SArnaud Pouliquen .shutdown = stm32_adfsdm_shutdown, 13355da0948SArnaud Pouliquen .prepare = stm32_adfsdm_dai_prepare, 13455da0948SArnaud Pouliquen .set_sysclk = stm32_adfsdm_set_sysclk, 13555da0948SArnaud Pouliquen }; 13655da0948SArnaud Pouliquen 13755da0948SArnaud Pouliquen static const struct snd_soc_dai_driver stm32_adfsdm_dai = { 13855da0948SArnaud Pouliquen .capture = { 13955da0948SArnaud Pouliquen .channels_min = 1, 14055da0948SArnaud Pouliquen .channels_max = 1, 1411e7f6e1cSOlivier Moysan .formats = SNDRV_PCM_FMTBIT_S16_LE | 1421e7f6e1cSOlivier Moysan SNDRV_PCM_FMTBIT_S32_LE, 1436101bf71SOlivier Moysan .rates = SNDRV_PCM_RATE_CONTINUOUS, 1446101bf71SOlivier Moysan .rate_min = 8000, 1456101bf71SOlivier Moysan .rate_max = 48000, 14655da0948SArnaud Pouliquen }, 14755da0948SArnaud Pouliquen .ops = &stm32_adfsdm_dai_ops, 14855da0948SArnaud Pouliquen }; 14955da0948SArnaud Pouliquen 15055da0948SArnaud Pouliquen static const struct snd_soc_component_driver stm32_adfsdm_dai_component = { 15155da0948SArnaud Pouliquen .name = "stm32_dfsdm_audio", 15255da0948SArnaud Pouliquen }; 15355da0948SArnaud Pouliquen 1548e55ea19SOlivier Moysan static void stm32_memcpy_32to16(void *dest, const void *src, size_t n) 1551e7f6e1cSOlivier Moysan { 1561e7f6e1cSOlivier Moysan unsigned int i = 0; 1571e7f6e1cSOlivier Moysan u16 *d = (u16 *)dest, *s = (u16 *)src; 1581e7f6e1cSOlivier Moysan 1591e7f6e1cSOlivier Moysan s++; 1608e55ea19SOlivier Moysan for (i = n >> 1; i > 0; i--) { 1611e7f6e1cSOlivier Moysan *d++ = *s++; 1621e7f6e1cSOlivier Moysan s++; 1631e7f6e1cSOlivier Moysan } 1641e7f6e1cSOlivier Moysan } 1651e7f6e1cSOlivier Moysan 16655da0948SArnaud Pouliquen static int stm32_afsdm_pcm_cb(const void *data, size_t size, void *private) 16755da0948SArnaud Pouliquen { 16855da0948SArnaud Pouliquen struct stm32_adfsdm_priv *priv = private; 169ddb4f06dSKuninori Morimoto struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(priv->substream); 17055da0948SArnaud Pouliquen u8 *pcm_buff = priv->pcm_buff; 17155da0948SArnaud Pouliquen u8 *src_buff = (u8 *)data; 17255da0948SArnaud Pouliquen unsigned int old_pos = priv->pos; 1731e7f6e1cSOlivier Moysan size_t buff_size = snd_pcm_lib_buffer_bytes(priv->substream); 1741e7f6e1cSOlivier Moysan size_t period_size = snd_pcm_lib_period_bytes(priv->substream); 1751e7f6e1cSOlivier Moysan size_t cur_size, src_size = size; 1761e7f6e1cSOlivier Moysan snd_pcm_format_t format = priv->substream->runtime->format; 1771e7f6e1cSOlivier Moysan 1781e7f6e1cSOlivier Moysan if (format == SNDRV_PCM_FORMAT_S16_LE) 1791e7f6e1cSOlivier Moysan src_size >>= 1; 1801e7f6e1cSOlivier Moysan cur_size = src_size; 18155da0948SArnaud Pouliquen 1828db339d6Sbenjamin.gaignard@linaro.org dev_dbg(rtd->dev, "%s: buff_add :%pK, pos = %d, size = %zu\n", 1831e7f6e1cSOlivier Moysan __func__, &pcm_buff[priv->pos], priv->pos, src_size); 18455da0948SArnaud Pouliquen 1851e7f6e1cSOlivier Moysan if ((priv->pos + src_size) > buff_size) { 1861e7f6e1cSOlivier Moysan if (format == SNDRV_PCM_FORMAT_S16_LE) 1878e55ea19SOlivier Moysan stm32_memcpy_32to16(&pcm_buff[priv->pos], src_buff, 1881e7f6e1cSOlivier Moysan buff_size - priv->pos); 1891e7f6e1cSOlivier Moysan else 1901e7f6e1cSOlivier Moysan memcpy(&pcm_buff[priv->pos], src_buff, 1911e7f6e1cSOlivier Moysan buff_size - priv->pos); 19255da0948SArnaud Pouliquen cur_size -= buff_size - priv->pos; 19355da0948SArnaud Pouliquen priv->pos = 0; 19455da0948SArnaud Pouliquen } 19555da0948SArnaud Pouliquen 1961e7f6e1cSOlivier Moysan if (format == SNDRV_PCM_FORMAT_S16_LE) 1978e55ea19SOlivier Moysan stm32_memcpy_32to16(&pcm_buff[priv->pos], 1981e7f6e1cSOlivier Moysan &src_buff[src_size - cur_size], cur_size); 1991e7f6e1cSOlivier Moysan else 2001e7f6e1cSOlivier Moysan memcpy(&pcm_buff[priv->pos], &src_buff[src_size - cur_size], 2011e7f6e1cSOlivier Moysan cur_size); 2021e7f6e1cSOlivier Moysan 20355da0948SArnaud Pouliquen priv->pos = (priv->pos + cur_size) % buff_size; 20455da0948SArnaud Pouliquen 2051e7f6e1cSOlivier Moysan if (cur_size != src_size || (old_pos && (old_pos % period_size < size))) 20655da0948SArnaud Pouliquen snd_pcm_period_elapsed(priv->substream); 20755da0948SArnaud Pouliquen 20855da0948SArnaud Pouliquen return 0; 20955da0948SArnaud Pouliquen } 21055da0948SArnaud Pouliquen 21121499089SKuninori Morimoto static int stm32_adfsdm_trigger(struct snd_soc_component *component, 21221499089SKuninori Morimoto struct snd_pcm_substream *substream, int cmd) 21355da0948SArnaud Pouliquen { 214ddb4f06dSKuninori Morimoto struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); 21555da0948SArnaud Pouliquen struct stm32_adfsdm_priv *priv = 216b1bee67cSKuninori Morimoto snd_soc_dai_get_drvdata(asoc_rtd_to_cpu(rtd, 0)); 21755da0948SArnaud Pouliquen 21855da0948SArnaud Pouliquen switch (cmd) { 21955da0948SArnaud Pouliquen case SNDRV_PCM_TRIGGER_START: 22055da0948SArnaud Pouliquen case SNDRV_PCM_TRIGGER_RESUME: 22155da0948SArnaud Pouliquen priv->pos = 0; 22255da0948SArnaud Pouliquen return stm32_dfsdm_get_buff_cb(priv->iio_ch->indio_dev, 22355da0948SArnaud Pouliquen stm32_afsdm_pcm_cb, priv); 22455da0948SArnaud Pouliquen case SNDRV_PCM_TRIGGER_SUSPEND: 22555da0948SArnaud Pouliquen case SNDRV_PCM_TRIGGER_STOP: 22655da0948SArnaud Pouliquen return stm32_dfsdm_release_buff_cb(priv->iio_ch->indio_dev); 22755da0948SArnaud Pouliquen } 22855da0948SArnaud Pouliquen 22955da0948SArnaud Pouliquen return -EINVAL; 23055da0948SArnaud Pouliquen } 23155da0948SArnaud Pouliquen 23221499089SKuninori Morimoto static int stm32_adfsdm_pcm_open(struct snd_soc_component *component, 23321499089SKuninori Morimoto struct snd_pcm_substream *substream) 23455da0948SArnaud Pouliquen { 235ddb4f06dSKuninori Morimoto struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); 236b1bee67cSKuninori Morimoto struct stm32_adfsdm_priv *priv = snd_soc_dai_get_drvdata(asoc_rtd_to_cpu(rtd, 0)); 23755da0948SArnaud Pouliquen int ret; 23855da0948SArnaud Pouliquen 23955da0948SArnaud Pouliquen ret = snd_soc_set_runtime_hwparams(substream, &stm32_adfsdm_pcm_hw); 24055da0948SArnaud Pouliquen if (!ret) 24155da0948SArnaud Pouliquen priv->substream = substream; 24255da0948SArnaud Pouliquen 24355da0948SArnaud Pouliquen return ret; 24455da0948SArnaud Pouliquen } 24555da0948SArnaud Pouliquen 24621499089SKuninori Morimoto static int stm32_adfsdm_pcm_close(struct snd_soc_component *component, 24721499089SKuninori Morimoto struct snd_pcm_substream *substream) 24855da0948SArnaud Pouliquen { 249ddb4f06dSKuninori Morimoto struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); 25055da0948SArnaud Pouliquen struct stm32_adfsdm_priv *priv = 251b1bee67cSKuninori Morimoto snd_soc_dai_get_drvdata(asoc_rtd_to_cpu(rtd, 0)); 25255da0948SArnaud Pouliquen 25355da0948SArnaud Pouliquen priv->substream = NULL; 25455da0948SArnaud Pouliquen 25555da0948SArnaud Pouliquen return 0; 25655da0948SArnaud Pouliquen } 25755da0948SArnaud Pouliquen 25855da0948SArnaud Pouliquen static snd_pcm_uframes_t stm32_adfsdm_pcm_pointer( 25921499089SKuninori Morimoto struct snd_soc_component *component, 26055da0948SArnaud Pouliquen struct snd_pcm_substream *substream) 26155da0948SArnaud Pouliquen { 262ddb4f06dSKuninori Morimoto struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); 26355da0948SArnaud Pouliquen struct stm32_adfsdm_priv *priv = 264b1bee67cSKuninori Morimoto snd_soc_dai_get_drvdata(asoc_rtd_to_cpu(rtd, 0)); 26555da0948SArnaud Pouliquen 26655da0948SArnaud Pouliquen return bytes_to_frames(substream->runtime, priv->pos); 26755da0948SArnaud Pouliquen } 26855da0948SArnaud Pouliquen 26921499089SKuninori Morimoto static int stm32_adfsdm_pcm_hw_params(struct snd_soc_component *component, 27021499089SKuninori Morimoto struct snd_pcm_substream *substream, 27155da0948SArnaud Pouliquen struct snd_pcm_hw_params *params) 27255da0948SArnaud Pouliquen { 273ddb4f06dSKuninori Morimoto struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); 27455da0948SArnaud Pouliquen struct stm32_adfsdm_priv *priv = 275b1bee67cSKuninori Morimoto snd_soc_dai_get_drvdata(asoc_rtd_to_cpu(rtd, 0)); 27655da0948SArnaud Pouliquen 27755da0948SArnaud Pouliquen priv->pcm_buff = substream->runtime->dma_area; 27855da0948SArnaud Pouliquen 27955da0948SArnaud Pouliquen return iio_channel_cb_set_buffer_watermark(priv->iio_cb, 28055da0948SArnaud Pouliquen params_period_size(params)); 28155da0948SArnaud Pouliquen } 28255da0948SArnaud Pouliquen 28321499089SKuninori Morimoto static int stm32_adfsdm_pcm_new(struct snd_soc_component *component, 28421499089SKuninori Morimoto struct snd_soc_pcm_runtime *rtd) 28555da0948SArnaud Pouliquen { 28655da0948SArnaud Pouliquen struct snd_pcm *pcm = rtd->pcm; 28755da0948SArnaud Pouliquen struct stm32_adfsdm_priv *priv = 288b1bee67cSKuninori Morimoto snd_soc_dai_get_drvdata(asoc_rtd_to_cpu(rtd, 0)); 28955da0948SArnaud Pouliquen unsigned int size = DFSDM_MAX_PERIODS * DFSDM_MAX_PERIOD_SIZE; 29055da0948SArnaud Pouliquen 2916f7aff35STakashi Iwai snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV, 29255da0948SArnaud Pouliquen priv->dev, size, size); 29318183edaSTakashi Iwai return 0; 29455da0948SArnaud Pouliquen } 29555da0948SArnaud Pouliquen 2969afaf9a5SOlivier Moysan static int stm32_adfsdm_dummy_cb(const void *data, void *private) 2979afaf9a5SOlivier Moysan { 2989afaf9a5SOlivier Moysan /* 2999afaf9a5SOlivier Moysan * This dummmy callback is requested by iio_channel_get_all_cb() API, 3009afaf9a5SOlivier Moysan * but the stm32_dfsdm_get_buff_cb() API is used instead, to optimize 3019afaf9a5SOlivier Moysan * DMA transfers. 3029afaf9a5SOlivier Moysan */ 3039afaf9a5SOlivier Moysan return 0; 3049afaf9a5SOlivier Moysan } 3059afaf9a5SOlivier Moysan 30666bf428eSKuninori Morimoto static struct snd_soc_component_driver stm32_adfsdm_soc_platform = { 30721499089SKuninori Morimoto .open = stm32_adfsdm_pcm_open, 30821499089SKuninori Morimoto .close = stm32_adfsdm_pcm_close, 30921499089SKuninori Morimoto .hw_params = stm32_adfsdm_pcm_hw_params, 31021499089SKuninori Morimoto .trigger = stm32_adfsdm_trigger, 31121499089SKuninori Morimoto .pointer = stm32_adfsdm_pcm_pointer, 31221499089SKuninori Morimoto .pcm_construct = stm32_adfsdm_pcm_new, 31355da0948SArnaud Pouliquen }; 31455da0948SArnaud Pouliquen 31555da0948SArnaud Pouliquen static const struct of_device_id stm32_adfsdm_of_match[] = { 31655da0948SArnaud Pouliquen {.compatible = "st,stm32h7-dfsdm-dai"}, 31755da0948SArnaud Pouliquen {} 31855da0948SArnaud Pouliquen }; 31955da0948SArnaud Pouliquen MODULE_DEVICE_TABLE(of, stm32_adfsdm_of_match); 32055da0948SArnaud Pouliquen 32155da0948SArnaud Pouliquen static int stm32_adfsdm_probe(struct platform_device *pdev) 32255da0948SArnaud Pouliquen { 32355da0948SArnaud Pouliquen struct stm32_adfsdm_priv *priv; 324c47255b6SOlivier Moysan struct snd_soc_component *component; 32555da0948SArnaud Pouliquen int ret; 32655da0948SArnaud Pouliquen 32755da0948SArnaud Pouliquen priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); 32855da0948SArnaud Pouliquen if (!priv) 32955da0948SArnaud Pouliquen return -ENOMEM; 33055da0948SArnaud Pouliquen 33155da0948SArnaud Pouliquen priv->dev = &pdev->dev; 33255da0948SArnaud Pouliquen priv->dai_drv = stm32_adfsdm_dai; 33319441e35SOlivier Moysan mutex_init(&priv->lock); 33455da0948SArnaud Pouliquen 33555da0948SArnaud Pouliquen dev_set_drvdata(&pdev->dev, priv); 33655da0948SArnaud Pouliquen 33755da0948SArnaud Pouliquen ret = devm_snd_soc_register_component(&pdev->dev, 33855da0948SArnaud Pouliquen &stm32_adfsdm_dai_component, 33955da0948SArnaud Pouliquen &priv->dai_drv, 1); 34055da0948SArnaud Pouliquen if (ret < 0) 34155da0948SArnaud Pouliquen return ret; 34255da0948SArnaud Pouliquen 34355da0948SArnaud Pouliquen /* Associate iio channel */ 34455da0948SArnaud Pouliquen priv->iio_ch = devm_iio_channel_get_all(&pdev->dev); 34555da0948SArnaud Pouliquen if (IS_ERR(priv->iio_ch)) 34655da0948SArnaud Pouliquen return PTR_ERR(priv->iio_ch); 34755da0948SArnaud Pouliquen 3489afaf9a5SOlivier Moysan priv->iio_cb = iio_channel_get_all_cb(&pdev->dev, &stm32_adfsdm_dummy_cb, NULL); 34955da0948SArnaud Pouliquen if (IS_ERR(priv->iio_cb)) 3506dee6722SWei Yongjun return PTR_ERR(priv->iio_cb); 35155da0948SArnaud Pouliquen 352c47255b6SOlivier Moysan component = devm_kzalloc(&pdev->dev, sizeof(*component), GFP_KERNEL); 353c47255b6SOlivier Moysan if (!component) 354c47255b6SOlivier Moysan return -ENOMEM; 355ea029dd8SCezary Rojewski 356ea029dd8SCezary Rojewski ret = snd_soc_component_initialize(component, 357ea029dd8SCezary Rojewski &stm32_adfsdm_soc_platform, 358ea029dd8SCezary Rojewski &pdev->dev); 359ea029dd8SCezary Rojewski if (ret < 0) 360ea029dd8SCezary Rojewski return ret; 361c47255b6SOlivier Moysan #ifdef CONFIG_DEBUG_FS 362c47255b6SOlivier Moysan component->debugfs_prefix = "pcm"; 363c47255b6SOlivier Moysan #endif 364c47255b6SOlivier Moysan 365ea029dd8SCezary Rojewski ret = snd_soc_add_component(component, NULL, 0); 36655da0948SArnaud Pouliquen if (ret < 0) 36755da0948SArnaud Pouliquen dev_err(&pdev->dev, "%s: Failed to register PCM platform\n", 36855da0948SArnaud Pouliquen __func__); 36955da0948SArnaud Pouliquen 37055da0948SArnaud Pouliquen return ret; 37155da0948SArnaud Pouliquen } 37255da0948SArnaud Pouliquen 373c47255b6SOlivier Moysan static int stm32_adfsdm_remove(struct platform_device *pdev) 374c47255b6SOlivier Moysan { 375c47255b6SOlivier Moysan snd_soc_unregister_component(&pdev->dev); 376c47255b6SOlivier Moysan 377c47255b6SOlivier Moysan return 0; 378c47255b6SOlivier Moysan } 379c47255b6SOlivier Moysan 38055da0948SArnaud Pouliquen static struct platform_driver stm32_adfsdm_driver = { 38155da0948SArnaud Pouliquen .driver = { 38255da0948SArnaud Pouliquen .name = STM32_ADFSDM_DRV_NAME, 38355da0948SArnaud Pouliquen .of_match_table = stm32_adfsdm_of_match, 38455da0948SArnaud Pouliquen }, 38555da0948SArnaud Pouliquen .probe = stm32_adfsdm_probe, 386c47255b6SOlivier Moysan .remove = stm32_adfsdm_remove, 38755da0948SArnaud Pouliquen }; 38855da0948SArnaud Pouliquen 38955da0948SArnaud Pouliquen module_platform_driver(stm32_adfsdm_driver); 39055da0948SArnaud Pouliquen 39155da0948SArnaud Pouliquen MODULE_DESCRIPTION("stm32 DFSDM DAI driver"); 39255da0948SArnaud Pouliquen MODULE_AUTHOR("Arnaud Pouliquen <arnaud.pouliquen@st.com>"); 39355da0948SArnaud Pouliquen MODULE_LICENSE("GPL v2"); 39455da0948SArnaud Pouliquen MODULE_ALIAS("platform:" STM32_ADFSDM_DRV_NAME); 395