diff options
Diffstat (limited to 'sound/soc/stm/stm32_adfsdm.c')
| -rw-r--r-- | sound/soc/stm/stm32_adfsdm.c | 84 |
1 files changed, 56 insertions, 28 deletions
diff --git a/sound/soc/stm/stm32_adfsdm.c b/sound/soc/stm/stm32_adfsdm.c index 16ff02953015..1797a91fea7a 100644 --- a/sound/soc/stm/stm32_adfsdm.c +++ b/sound/soc/stm/stm32_adfsdm.c @@ -12,7 +12,7 @@ #include <linux/mutex.h> #include <linux/platform_device.h> #include <linux/slab.h> - +#include <linux/pm_runtime.h> #include <linux/iio/iio.h> #include <linux/iio/consumer.h> #include <linux/iio/adc/stm32-dfsdm-adc.h> @@ -47,9 +47,6 @@ static const struct snd_pcm_hardware stm32_adfsdm_pcm_hw = { SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_PAUSE, .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE, - .rate_min = 8000, - .rate_max = 32000, - .channels_min = 1, .channels_max = 1, @@ -120,7 +117,7 @@ static int stm32_adfsdm_set_sysclk(struct snd_soc_dai *dai, int clk_id, /* Set IIO frequency if CODEC is master as clock comes from SPI_IN */ - snprintf(str_freq, sizeof(str_freq), "%d\n", freq); + snprintf(str_freq, sizeof(str_freq), "%u\n", freq); size = iio_write_channel_ext_info(priv->iio_ch, "spi_clk_freq", str_freq, sizeof(str_freq)); if (size != sizeof(str_freq)) { @@ -143,14 +140,16 @@ static const struct snd_soc_dai_driver stm32_adfsdm_dai = { .channels_max = 1, .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE, - .rates = (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 | - SNDRV_PCM_RATE_32000), + .rates = SNDRV_PCM_RATE_CONTINUOUS, + .rate_min = 8000, + .rate_max = 192000, }, .ops = &stm32_adfsdm_dai_ops, }; static const struct snd_soc_component_driver stm32_adfsdm_dai_component = { .name = "stm32_dfsdm_audio", + .legacy_dai_naming = 1, }; static void stm32_memcpy_32to16(void *dest, const void *src, size_t n) @@ -168,7 +167,7 @@ static void stm32_memcpy_32to16(void *dest, const void *src, size_t n) static int stm32_afsdm_pcm_cb(const void *data, size_t size, void *private) { struct stm32_adfsdm_priv *priv = private; - struct snd_soc_pcm_runtime *rtd = priv->substream->private_data; + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(priv->substream); u8 *pcm_buff = priv->pcm_buff; u8 *src_buff = (u8 *)data; unsigned int old_pos = priv->pos; @@ -181,7 +180,7 @@ static int stm32_afsdm_pcm_cb(const void *data, size_t size, void *private) src_size >>= 1; cur_size = src_size; - dev_dbg(rtd->dev, "%s: buff_add :%pK, pos = %d, size = %zu\n", + dev_dbg(rtd->dev, "%s: buff_add :%p, pos = %d, size = %zu\n", __func__, &pcm_buff[priv->pos], priv->pos, src_size); if ((priv->pos + src_size) > buff_size) { @@ -213,9 +212,9 @@ static int stm32_afsdm_pcm_cb(const void *data, size_t size, void *private) static int stm32_adfsdm_trigger(struct snd_soc_component *component, struct snd_pcm_substream *substream, int cmd) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); struct stm32_adfsdm_priv *priv = - snd_soc_dai_get_drvdata(asoc_rtd_to_cpu(rtd, 0)); + snd_soc_dai_get_drvdata(snd_soc_rtd_to_cpu(rtd, 0)); switch (cmd) { case SNDRV_PCM_TRIGGER_START: @@ -234,8 +233,8 @@ static int stm32_adfsdm_trigger(struct snd_soc_component *component, static int stm32_adfsdm_pcm_open(struct snd_soc_component *component, struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct stm32_adfsdm_priv *priv = snd_soc_dai_get_drvdata(asoc_rtd_to_cpu(rtd, 0)); + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); + struct stm32_adfsdm_priv *priv = snd_soc_dai_get_drvdata(snd_soc_rtd_to_cpu(rtd, 0)); int ret; ret = snd_soc_set_runtime_hwparams(substream, &stm32_adfsdm_pcm_hw); @@ -248,9 +247,9 @@ static int stm32_adfsdm_pcm_open(struct snd_soc_component *component, static int stm32_adfsdm_pcm_close(struct snd_soc_component *component, struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); struct stm32_adfsdm_priv *priv = - snd_soc_dai_get_drvdata(asoc_rtd_to_cpu(rtd, 0)); + snd_soc_dai_get_drvdata(snd_soc_rtd_to_cpu(rtd, 0)); priv->substream = NULL; @@ -261,9 +260,9 @@ static snd_pcm_uframes_t stm32_adfsdm_pcm_pointer( struct snd_soc_component *component, struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); struct stm32_adfsdm_priv *priv = - snd_soc_dai_get_drvdata(asoc_rtd_to_cpu(rtd, 0)); + snd_soc_dai_get_drvdata(snd_soc_rtd_to_cpu(rtd, 0)); return bytes_to_frames(substream->runtime, priv->pos); } @@ -272,9 +271,9 @@ static int stm32_adfsdm_pcm_hw_params(struct snd_soc_component *component, struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); struct stm32_adfsdm_priv *priv = - snd_soc_dai_get_drvdata(asoc_rtd_to_cpu(rtd, 0)); + snd_soc_dai_get_drvdata(snd_soc_rtd_to_cpu(rtd, 0)); priv->pcm_buff = substream->runtime->dma_area; @@ -287,7 +286,7 @@ static int stm32_adfsdm_pcm_new(struct snd_soc_component *component, { struct snd_pcm *pcm = rtd->pcm; struct stm32_adfsdm_priv *priv = - snd_soc_dai_get_drvdata(asoc_rtd_to_cpu(rtd, 0)); + snd_soc_dai_get_drvdata(snd_soc_rtd_to_cpu(rtd, 0)); unsigned int size = DFSDM_MAX_PERIODS * DFSDM_MAX_PERIOD_SIZE; snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV, @@ -295,7 +294,22 @@ static int stm32_adfsdm_pcm_new(struct snd_soc_component *component, return 0; } -static struct snd_soc_component_driver stm32_adfsdm_soc_platform = { +static int stm32_adfsdm_dummy_cb(const void *data, void *private) +{ + /* + * This dummy callback is requested by iio_channel_get_all_cb() API, + * but the stm32_dfsdm_get_buff_cb() API is used instead, to optimize + * DMA transfers. + */ + return 0; +} + +static void stm32_adfsdm_cleanup(void *data) +{ + iio_channel_release_all_cb(data); +} + +static const struct snd_soc_component_driver stm32_adfsdm_soc_platform = { .open = stm32_adfsdm_pcm_open, .close = stm32_adfsdm_pcm_close, .hw_params = stm32_adfsdm_pcm_hw_params, @@ -337,31 +351,45 @@ static int stm32_adfsdm_probe(struct platform_device *pdev) if (IS_ERR(priv->iio_ch)) return PTR_ERR(priv->iio_ch); - priv->iio_cb = iio_channel_get_all_cb(&pdev->dev, NULL, NULL); + priv->iio_cb = iio_channel_get_all_cb(&pdev->dev, &stm32_adfsdm_dummy_cb, NULL); if (IS_ERR(priv->iio_cb)) return PTR_ERR(priv->iio_cb); + ret = devm_add_action_or_reset(&pdev->dev, stm32_adfsdm_cleanup, priv->iio_cb); + if (ret < 0) { + dev_err(&pdev->dev, "Unable to add action\n"); + return ret; + } + component = devm_kzalloc(&pdev->dev, sizeof(*component), GFP_KERNEL); if (!component) return -ENOMEM; + + ret = snd_soc_component_initialize(component, + &stm32_adfsdm_soc_platform, + &pdev->dev); + if (ret < 0) + return ret; #ifdef CONFIG_DEBUG_FS component->debugfs_prefix = "pcm"; #endif - ret = snd_soc_add_component(&pdev->dev, component, - &stm32_adfsdm_soc_platform, NULL, 0); - if (ret < 0) + ret = snd_soc_add_component(component, NULL, 0); + if (ret < 0) { dev_err(&pdev->dev, "%s: Failed to register PCM platform\n", __func__); + return ret; + } + + pm_runtime_enable(&pdev->dev); return ret; } -static int stm32_adfsdm_remove(struct platform_device *pdev) +static void stm32_adfsdm_remove(struct platform_device *pdev) { snd_soc_unregister_component(&pdev->dev); - - return 0; + pm_runtime_disable(&pdev->dev); } static struct platform_driver stm32_adfsdm_driver = { |
