From 1f93a7dfd1f8d5ff7a5c53246c7534fe2332d6f4 Mon Sep 17 00:00:00 2001 From: hc <hc@nodka.com> Date: Mon, 11 Dec 2023 02:46:07 +0000 Subject: [PATCH] add audio --- kernel/sound/soc/stm/stm32_adfsdm.c | 152 +++++++++++++++++++++++++++----------------------- 1 files changed, 82 insertions(+), 70 deletions(-) diff --git a/kernel/sound/soc/stm/stm32_adfsdm.c b/kernel/sound/soc/stm/stm32_adfsdm.c index 24948b9..c403198 100644 --- a/kernel/sound/soc/stm/stm32_adfsdm.c +++ b/kernel/sound/soc/stm/stm32_adfsdm.c @@ -44,11 +44,8 @@ static const struct snd_pcm_hardware stm32_adfsdm_pcm_hw = { .info = SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER | - SNDRV_PCM_INFO_PAUSE, - .formats = SNDRV_PCM_FMTBIT_S32_LE, - - .rate_min = 8000, - .rate_max = 32000, + 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, @@ -141,9 +138,11 @@ .capture = { .channels_min = 1, .channels_max = 1, - .formats = SNDRV_PCM_FMTBIT_S32_LE, - .rates = (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 | - SNDRV_PCM_RATE_32000), + .formats = SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S32_LE, + .rates = SNDRV_PCM_RATE_CONTINUOUS, + .rate_min = 8000, + .rate_max = 48000, }, .ops = &stm32_adfsdm_dai_ops, }; @@ -152,40 +151,69 @@ .name = "stm32_dfsdm_audio", }; +static void stm32_memcpy_32to16(void *dest, const void *src, size_t n) +{ + unsigned int i = 0; + u16 *d = (u16 *)dest, *s = (u16 *)src; + + s++; + for (i = n >> 1; i > 0; i--) { + *d++ = *s++; + s++; + } +} + 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 = asoc_substream_to_rtd(priv->substream); u8 *pcm_buff = priv->pcm_buff; u8 *src_buff = (u8 *)data; - unsigned int buff_size = snd_pcm_lib_buffer_bytes(priv->substream); - unsigned int period_size = snd_pcm_lib_period_bytes(priv->substream); unsigned int old_pos = priv->pos; - unsigned int cur_size = size; + size_t buff_size = snd_pcm_lib_buffer_bytes(priv->substream); + size_t period_size = snd_pcm_lib_period_bytes(priv->substream); + size_t cur_size, src_size = size; + snd_pcm_format_t format = priv->substream->runtime->format; + + if (format == SNDRV_PCM_FORMAT_S16_LE) + src_size >>= 1; + cur_size = src_size; dev_dbg(rtd->dev, "%s: buff_add :%pK, pos = %d, size = %zu\n", - __func__, &pcm_buff[priv->pos], priv->pos, size); + __func__, &pcm_buff[priv->pos], priv->pos, src_size); - if ((priv->pos + size) > buff_size) { - memcpy(&pcm_buff[priv->pos], src_buff, buff_size - priv->pos); + if ((priv->pos + src_size) > buff_size) { + if (format == SNDRV_PCM_FORMAT_S16_LE) + stm32_memcpy_32to16(&pcm_buff[priv->pos], src_buff, + buff_size - priv->pos); + else + memcpy(&pcm_buff[priv->pos], src_buff, + buff_size - priv->pos); cur_size -= buff_size - priv->pos; priv->pos = 0; } - memcpy(&pcm_buff[priv->pos], &src_buff[size - cur_size], cur_size); + if (format == SNDRV_PCM_FORMAT_S16_LE) + stm32_memcpy_32to16(&pcm_buff[priv->pos], + &src_buff[src_size - cur_size], cur_size); + else + memcpy(&pcm_buff[priv->pos], &src_buff[src_size - cur_size], + cur_size); + priv->pos = (priv->pos + cur_size) % buff_size; - if (cur_size != size || (old_pos && (old_pos % period_size < size))) + if (cur_size != src_size || (old_pos && (old_pos % period_size < size))) snd_pcm_period_elapsed(priv->substream); return 0; } -static int stm32_adfsdm_trigger(struct snd_pcm_substream *substream, int cmd) +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 = asoc_substream_to_rtd(substream); struct stm32_adfsdm_priv *priv = - snd_soc_dai_get_drvdata(rtd->cpu_dai); + snd_soc_dai_get_drvdata(asoc_rtd_to_cpu(rtd, 0)); switch (cmd) { case SNDRV_PCM_TRIGGER_START: @@ -201,10 +229,11 @@ return -EINVAL; } -static int stm32_adfsdm_pcm_open(struct snd_pcm_substream *substream) +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(rtd->cpu_dai); + 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)); int ret; ret = snd_soc_set_runtime_hwparams(substream, &stm32_adfsdm_pcm_hw); @@ -214,85 +243,63 @@ return ret; } -static int stm32_adfsdm_pcm_close(struct snd_pcm_substream *substream) +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 = asoc_substream_to_rtd(substream); struct stm32_adfsdm_priv *priv = - snd_soc_dai_get_drvdata(rtd->cpu_dai); + snd_soc_dai_get_drvdata(asoc_rtd_to_cpu(rtd, 0)); - snd_pcm_lib_free_pages(substream); priv->substream = NULL; return 0; } 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 = asoc_substream_to_rtd(substream); struct stm32_adfsdm_priv *priv = - snd_soc_dai_get_drvdata(rtd->cpu_dai); + snd_soc_dai_get_drvdata(asoc_rtd_to_cpu(rtd, 0)); return bytes_to_frames(substream->runtime, priv->pos); } -static int stm32_adfsdm_pcm_hw_params(struct snd_pcm_substream *substream, +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 = asoc_substream_to_rtd(substream); struct stm32_adfsdm_priv *priv = - snd_soc_dai_get_drvdata(rtd->cpu_dai); - int ret; + snd_soc_dai_get_drvdata(asoc_rtd_to_cpu(rtd, 0)); - ret = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(params)); - if (ret < 0) - return ret; priv->pcm_buff = substream->runtime->dma_area; return iio_channel_cb_set_buffer_watermark(priv->iio_cb, params_period_size(params)); } -static int stm32_adfsdm_pcm_hw_free(struct snd_pcm_substream *substream) -{ - snd_pcm_lib_free_pages(substream); - - return 0; -} - -static struct snd_pcm_ops stm32_adfsdm_pcm_ops = { - .open = stm32_adfsdm_pcm_open, - .close = stm32_adfsdm_pcm_close, - .hw_params = stm32_adfsdm_pcm_hw_params, - .hw_free = stm32_adfsdm_pcm_hw_free, - .trigger = stm32_adfsdm_trigger, - .pointer = stm32_adfsdm_pcm_pointer, -}; - -static int stm32_adfsdm_pcm_new(struct snd_soc_pcm_runtime *rtd) +static int stm32_adfsdm_pcm_new(struct snd_soc_component *component, + struct snd_soc_pcm_runtime *rtd) { struct snd_pcm *pcm = rtd->pcm; struct stm32_adfsdm_priv *priv = - snd_soc_dai_get_drvdata(rtd->cpu_dai); + snd_soc_dai_get_drvdata(asoc_rtd_to_cpu(rtd, 0)); unsigned int size = DFSDM_MAX_PERIODS * DFSDM_MAX_PERIOD_SIZE; - return snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, - priv->dev, size, size); -} - -static void stm32_adfsdm_pcm_free(struct snd_pcm *pcm) -{ - struct snd_pcm_substream *substream; - - substream = pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream; - if (substream) - snd_pcm_lib_preallocate_free_for_all(pcm); + snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV, + priv->dev, size, size); + return 0; } static struct snd_soc_component_driver stm32_adfsdm_soc_platform = { - .ops = &stm32_adfsdm_pcm_ops, - .pcm_new = stm32_adfsdm_pcm_new, - .pcm_free = stm32_adfsdm_pcm_free, + .open = stm32_adfsdm_pcm_open, + .close = stm32_adfsdm_pcm_close, + .hw_params = stm32_adfsdm_pcm_hw_params, + .trigger = stm32_adfsdm_trigger, + .pointer = stm32_adfsdm_pcm_pointer, + .pcm_construct = stm32_adfsdm_pcm_new, }; static const struct of_device_id stm32_adfsdm_of_match[] = { @@ -335,12 +342,17 @@ 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); + ret = snd_soc_add_component(component, NULL, 0); if (ret < 0) dev_err(&pdev->dev, "%s: Failed to register PCM platform\n", __func__); -- Gitblit v1.6.2