diff options
Diffstat (limited to 'sound/soc/stm/stm32_adfsdm.c')
-rw-r--r-- | sound/soc/stm/stm32_adfsdm.c | 73 |
1 files changed, 48 insertions, 25 deletions
diff --git a/sound/soc/stm/stm32_adfsdm.c b/sound/soc/stm/stm32_adfsdm.c index ec27c13af04f..fb5dd9a68bea 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 = 48000, }, .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 = asoc_substream_to_rtd(priv->substream); + 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; @@ -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 = asoc_substream_to_rtd(substream); + 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 = asoc_substream_to_rtd(substream); - 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 = asoc_substream_to_rtd(substream); + 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 = asoc_substream_to_rtd(substream); + 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 = asoc_substream_to_rtd(substream); + 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,6 +294,21 @@ static int stm32_adfsdm_pcm_new(struct snd_soc_component *component, return 0; } +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 struct snd_soc_component_driver stm32_adfsdm_soc_platform = { .open = stm32_adfsdm_pcm_open, .close = stm32_adfsdm_pcm_close, @@ -337,10 +351,16 @@ 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; @@ -355,18 +375,21 @@ static int stm32_adfsdm_probe(struct platform_device *pdev) #endif ret = snd_soc_add_component(component, NULL, 0); - if (ret < 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 = { @@ -375,7 +398,7 @@ static struct platform_driver stm32_adfsdm_driver = { .of_match_table = stm32_adfsdm_of_match, }, .probe = stm32_adfsdm_probe, - .remove = stm32_adfsdm_remove, + .remove_new = stm32_adfsdm_remove, }; module_platform_driver(stm32_adfsdm_driver); |