Re: [PATCH v6 09/10] ASoC: fsl: Add support for QMC audio

2023-02-17 Thread Christophe Leroy


Le 17/02/2023 à 15:56, Herve Codina a écrit :
> The QMC audio is an ASoC component which provides DAIs
> that use the QMC (QUICC Multichannel Controller) to transfer
> the audio data.
> 
> It provides as many DAIs as the number of QMC channels it
> references.
> 
> Signed-off-by: Herve Codina 

Reviewed-by: Christophe Leroy 
Tested-by: Christophe Leroy 

> ---
>   sound/soc/fsl/Kconfig |   9 +
>   sound/soc/fsl/Makefile|   2 +
>   sound/soc/fsl/fsl_qmc_audio.c | 735 ++
>   3 files changed, 746 insertions(+)
>   create mode 100644 sound/soc/fsl/fsl_qmc_audio.c
> 
> diff --git a/sound/soc/fsl/Kconfig b/sound/soc/fsl/Kconfig
> index 614eceda6b9e..17db29c25d96 100644
> --- a/sound/soc/fsl/Kconfig
> +++ b/sound/soc/fsl/Kconfig
> @@ -172,6 +172,15 @@ config SND_MPC52xx_DMA
>   config SND_SOC_POWERPC_DMA
>   tristate
>   
> +config SND_SOC_POWERPC_QMC_AUDIO
> + tristate "QMC ALSA SoC support"
> + depends on CPM_QMC
> + help
> +   ALSA SoC Audio support using the Freescale QUICC Multichannel
> +   Controller (QMC).
> +   Say Y or M if you want to add support for SoC audio using Freescale
> +   QMC.
> +
>   comment "SoC Audio support for Freescale PPC boards:"
>   
>   config SND_SOC_MPC8610_HPCD
> diff --git a/sound/soc/fsl/Makefile b/sound/soc/fsl/Makefile
> index b54beb1a66fa..8db7e97d0bd5 100644
> --- a/sound/soc/fsl/Makefile
> +++ b/sound/soc/fsl/Makefile
> @@ -28,6 +28,7 @@ snd-soc-fsl-easrc-objs := fsl_easrc.o
>   snd-soc-fsl-xcvr-objs := fsl_xcvr.o
>   snd-soc-fsl-aud2htx-objs := fsl_aud2htx.o
>   snd-soc-fsl-rpmsg-objs := fsl_rpmsg.o
> +snd-soc-fsl-qmc-audio-objs := fsl_qmc_audio.o
>   
>   obj-$(CONFIG_SND_SOC_FSL_AUDMIX) += snd-soc-fsl-audmix.o
>   obj-$(CONFIG_SND_SOC_FSL_ASOC_CARD) += snd-soc-fsl-asoc-card.o
> @@ -44,6 +45,7 @@ obj-$(CONFIG_SND_SOC_POWERPC_DMA) += snd-soc-fsl-dma.o
>   obj-$(CONFIG_SND_SOC_FSL_XCVR) += snd-soc-fsl-xcvr.o
>   obj-$(CONFIG_SND_SOC_FSL_AUD2HTX) += snd-soc-fsl-aud2htx.o
>   obj-$(CONFIG_SND_SOC_FSL_RPMSG) += snd-soc-fsl-rpmsg.o
> +obj-$(CONFIG_SND_SOC_POWERPC_QMC_AUDIO) += snd-soc-fsl-qmc-audio.o
>   
>   # MPC5200 Platform Support
>   obj-$(CONFIG_SND_MPC52xx_DMA) += mpc5200_dma.o
> diff --git a/sound/soc/fsl/fsl_qmc_audio.c b/sound/soc/fsl/fsl_qmc_audio.c
> new file mode 100644
> index ..7cbb8e4758cc
> --- /dev/null
> +++ b/sound/soc/fsl/fsl_qmc_audio.c
> @@ -0,0 +1,735 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * ALSA SoC using the QUICC Multichannel Controller (QMC)
> + *
> + * Copyright 2022 CS GROUP France
> + *
> + * Author: Herve Codina 
> + */
> +
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +
> +struct qmc_dai {
> + char *name;
> + int id;
> + struct device *dev;
> + struct qmc_chan *qmc_chan;
> + unsigned int nb_tx_ts;
> + unsigned int nb_rx_ts;
> +};
> +
> +struct qmc_audio {
> + struct device *dev;
> + unsigned int num_dais;
> + struct qmc_dai *dais;
> + struct snd_soc_dai_driver *dai_drivers;
> +};
> +
> +struct qmc_dai_prtd {
> + struct qmc_dai *qmc_dai;
> + dma_addr_t dma_buffer_start;
> + dma_addr_t period_ptr_submitted;
> + dma_addr_t period_ptr_ended;
> + dma_addr_t dma_buffer_end;
> + size_t period_size;
> + struct snd_pcm_substream *substream;
> +};
> +
> +static int qmc_audio_pcm_construct(struct snd_soc_component *component,
> +struct snd_soc_pcm_runtime *rtd)
> +{
> + struct snd_card *card = rtd->card->snd_card;
> + int ret;
> +
> + ret = dma_coerce_mask_and_coherent(card->dev, DMA_BIT_MASK(32));
> + if (ret)
> + return ret;
> +
> + snd_pcm_set_managed_buffer_all(rtd->pcm, SNDRV_DMA_TYPE_DEV, card->dev,
> +64*1024, 64*1024);
> + return 0;
> +}
> +
> +static int qmc_audio_pcm_hw_params(struct snd_soc_component *component,
> +struct snd_pcm_substream *substream,
> +struct snd_pcm_hw_params *params)
> +{
> + struct snd_pcm_runtime *runtime = substream->runtime;
> + struct qmc_dai_prtd *prtd = substream->runtime->private_data;
> +
> + prtd->dma_buffer_start = runtime->dma_addr;
> + prtd->dma_buffer_end = runtime->dma_addr + params_buffer_bytes(params);
> + prtd->period_size = params_period_bytes(params);
> + prtd->period_ptr_submitted = prtd->dma_buffer_start;
> + prtd->period_ptr_ended = prtd->dma_buffer_start;
> + prtd->substream = substream;
> +
> + return 0;
> +}
> +
> +static void qmc_audio_pcm_write_complete(void *context)
> +{
> + struct qmc_dai_prtd *prtd = context;
> + int ret;
> +
> + prtd->period_ptr_ended += prtd->period_size;
> + if (prtd->period_ptr_ended >= prtd->dma_buffer_end)
> + prtd->period_ptr_ended = prtd->dma_buffer_start;
> +
> + prtd->period_ptr_submitted 

[PATCH v6 09/10] ASoC: fsl: Add support for QMC audio

2023-02-17 Thread Herve Codina
The QMC audio is an ASoC component which provides DAIs
that use the QMC (QUICC Multichannel Controller) to transfer
the audio data.

It provides as many DAIs as the number of QMC channels it
references.

Signed-off-by: Herve Codina 
---
 sound/soc/fsl/Kconfig |   9 +
 sound/soc/fsl/Makefile|   2 +
 sound/soc/fsl/fsl_qmc_audio.c | 735 ++
 3 files changed, 746 insertions(+)
 create mode 100644 sound/soc/fsl/fsl_qmc_audio.c

diff --git a/sound/soc/fsl/Kconfig b/sound/soc/fsl/Kconfig
index 614eceda6b9e..17db29c25d96 100644
--- a/sound/soc/fsl/Kconfig
+++ b/sound/soc/fsl/Kconfig
@@ -172,6 +172,15 @@ config SND_MPC52xx_DMA
 config SND_SOC_POWERPC_DMA
tristate
 
+config SND_SOC_POWERPC_QMC_AUDIO
+   tristate "QMC ALSA SoC support"
+   depends on CPM_QMC
+   help
+ ALSA SoC Audio support using the Freescale QUICC Multichannel
+ Controller (QMC).
+ Say Y or M if you want to add support for SoC audio using Freescale
+ QMC.
+
 comment "SoC Audio support for Freescale PPC boards:"
 
 config SND_SOC_MPC8610_HPCD
diff --git a/sound/soc/fsl/Makefile b/sound/soc/fsl/Makefile
index b54beb1a66fa..8db7e97d0bd5 100644
--- a/sound/soc/fsl/Makefile
+++ b/sound/soc/fsl/Makefile
@@ -28,6 +28,7 @@ snd-soc-fsl-easrc-objs := fsl_easrc.o
 snd-soc-fsl-xcvr-objs := fsl_xcvr.o
 snd-soc-fsl-aud2htx-objs := fsl_aud2htx.o
 snd-soc-fsl-rpmsg-objs := fsl_rpmsg.o
+snd-soc-fsl-qmc-audio-objs := fsl_qmc_audio.o
 
 obj-$(CONFIG_SND_SOC_FSL_AUDMIX) += snd-soc-fsl-audmix.o
 obj-$(CONFIG_SND_SOC_FSL_ASOC_CARD) += snd-soc-fsl-asoc-card.o
@@ -44,6 +45,7 @@ obj-$(CONFIG_SND_SOC_POWERPC_DMA) += snd-soc-fsl-dma.o
 obj-$(CONFIG_SND_SOC_FSL_XCVR) += snd-soc-fsl-xcvr.o
 obj-$(CONFIG_SND_SOC_FSL_AUD2HTX) += snd-soc-fsl-aud2htx.o
 obj-$(CONFIG_SND_SOC_FSL_RPMSG) += snd-soc-fsl-rpmsg.o
+obj-$(CONFIG_SND_SOC_POWERPC_QMC_AUDIO) += snd-soc-fsl-qmc-audio.o
 
 # MPC5200 Platform Support
 obj-$(CONFIG_SND_MPC52xx_DMA) += mpc5200_dma.o
diff --git a/sound/soc/fsl/fsl_qmc_audio.c b/sound/soc/fsl/fsl_qmc_audio.c
new file mode 100644
index ..7cbb8e4758cc
--- /dev/null
+++ b/sound/soc/fsl/fsl_qmc_audio.c
@@ -0,0 +1,735 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * ALSA SoC using the QUICC Multichannel Controller (QMC)
+ *
+ * Copyright 2022 CS GROUP France
+ *
+ * Author: Herve Codina 
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+struct qmc_dai {
+   char *name;
+   int id;
+   struct device *dev;
+   struct qmc_chan *qmc_chan;
+   unsigned int nb_tx_ts;
+   unsigned int nb_rx_ts;
+};
+
+struct qmc_audio {
+   struct device *dev;
+   unsigned int num_dais;
+   struct qmc_dai *dais;
+   struct snd_soc_dai_driver *dai_drivers;
+};
+
+struct qmc_dai_prtd {
+   struct qmc_dai *qmc_dai;
+   dma_addr_t dma_buffer_start;
+   dma_addr_t period_ptr_submitted;
+   dma_addr_t period_ptr_ended;
+   dma_addr_t dma_buffer_end;
+   size_t period_size;
+   struct snd_pcm_substream *substream;
+};
+
+static int qmc_audio_pcm_construct(struct snd_soc_component *component,
+  struct snd_soc_pcm_runtime *rtd)
+{
+   struct snd_card *card = rtd->card->snd_card;
+   int ret;
+
+   ret = dma_coerce_mask_and_coherent(card->dev, DMA_BIT_MASK(32));
+   if (ret)
+   return ret;
+
+   snd_pcm_set_managed_buffer_all(rtd->pcm, SNDRV_DMA_TYPE_DEV, card->dev,
+  64*1024, 64*1024);
+   return 0;
+}
+
+static int qmc_audio_pcm_hw_params(struct snd_soc_component *component,
+  struct snd_pcm_substream *substream,
+  struct snd_pcm_hw_params *params)
+{
+   struct snd_pcm_runtime *runtime = substream->runtime;
+   struct qmc_dai_prtd *prtd = substream->runtime->private_data;
+
+   prtd->dma_buffer_start = runtime->dma_addr;
+   prtd->dma_buffer_end = runtime->dma_addr + params_buffer_bytes(params);
+   prtd->period_size = params_period_bytes(params);
+   prtd->period_ptr_submitted = prtd->dma_buffer_start;
+   prtd->period_ptr_ended = prtd->dma_buffer_start;
+   prtd->substream = substream;
+
+   return 0;
+}
+
+static void qmc_audio_pcm_write_complete(void *context)
+{
+   struct qmc_dai_prtd *prtd = context;
+   int ret;
+
+   prtd->period_ptr_ended += prtd->period_size;
+   if (prtd->period_ptr_ended >= prtd->dma_buffer_end)
+   prtd->period_ptr_ended = prtd->dma_buffer_start;
+
+   prtd->period_ptr_submitted += prtd->period_size;
+   if (prtd->period_ptr_submitted >= prtd->dma_buffer_end)
+   prtd->period_ptr_submitted = prtd->dma_buffer_start;
+
+   ret = qmc_chan_write_submit(prtd->qmc_dai->qmc_chan,
+   prtd->period_ptr_submitted, prtd->period_size,
+   qmc_audio_pcm_write_complete,