Re: [PATCH 2/3] ASoC: stm32: sai: add iec958 controls support

From: Arnaud Pouliquen
Date: Tue Jun 05 2018 - 11:56:35 EST


Hi Olivier,

On 03/13/2018 05:27 PM, Olivier MOYSAN wrote:
> Add support of iec958 controls for STM32 SAI.
>
> Signed-off-by: Olivier Moysan <olivier.moysan@xxxxxx>
> ---
> Âsound/core/pcm_iec958.cÂÂÂÂÂÂ |ÂÂ 1 +
> Âsound/soc/stm/KconfigÂÂÂÂÂÂÂÂ |ÂÂ 1 +
> Âsound/soc/stm/stm32_sai_sub.c | 101
> +++++++++++++++++++++++++++++++++++++-----
> Â3 files changed, 91 insertions(+), 12 deletions(-)
>
> diff --git a/sound/core/pcm_iec958.c b/sound/core/pcm_iec958.c
> index aba1f522e98a..c34735ac3c48 100644
> --- a/sound/core/pcm_iec958.c
> +++ b/sound/core/pcm_iec958.c
> @@ -19,6 +19,7 @@ static int snd_pcm_iec958_info(struct snd_kcontrol
> *kcontrol,
> Â{
> ÂÂÂÂÂÂÂÂ uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
> ÂÂÂÂÂÂÂÂ uinfo->count = 1;
> +
> ÂÂÂÂÂÂÂÂ return 0;
> Â}
Seems that this should be part of your patch 1/3

Regards,

Arnaud
> Â
> diff --git a/sound/soc/stm/Kconfig b/sound/soc/stm/Kconfig
> index 48f9ddd94016..9b2681397dba 100644
> --- a/sound/soc/stm/Kconfig
> +++ b/sound/soc/stm/Kconfig
> @@ -6,6 +6,7 @@ config SND_SOC_STM32_SAI
> ÂÂÂÂÂÂÂÂ depends on SND_SOC
> ÂÂÂÂÂÂÂÂ select SND_SOC_GENERIC_DMAENGINE_PCM
> ÂÂÂÂÂÂÂÂ select REGMAP_MMIO
> +ÂÂÂÂÂÂ select SND_PCM_IEC958
> ÂÂÂÂÂÂÂÂ help
> ÂÂÂÂÂÂÂÂÂÂ Say Y if you want to enable SAI for STM32
> Â
> diff --git a/sound/soc/stm/stm32_sai_sub.c b/sound/soc/stm/stm32_sai_sub.c
> index cfeb219e1d78..c2e487e133aa 100644
> --- a/sound/soc/stm/stm32_sai_sub.c
> +++ b/sound/soc/stm/stm32_sai_sub.c
> @@ -26,6 +26,7 @@
> Â#include <sound/asoundef.h>
> Â#include <sound/core.h>
> Â#include <sound/dmaengine_pcm.h>
> +#include <sound/pcm_iec958.h>
> Â#include <sound/pcm_params.h>
> Â
> Â#include "stm32_sai.h"
> @@ -96,7 +97,7 @@
> Â * @slot_mask: rx or tx active slots mask. set at init or at runtime
> Â * @data_size: PCM data width. corresponds to PCM substream width.
> Â * @spdif_frm_cnt: S/PDIF playback frame counter
> - * @spdif_status_bits: S/PDIF status bits
> + * @snd_aes_iec958: iec958 data
> Â */
> Âstruct stm32_sai_sub_data {
> ÂÂÂÂÂÂÂÂ struct platform_device *pdev;
> @@ -125,7 +126,7 @@ struct stm32_sai_sub_data {
> ÂÂÂÂÂÂÂÂ int slot_mask;
> ÂÂÂÂÂÂÂÂ int data_size;
> ÂÂÂÂÂÂÂÂ unsigned int spdif_frm_cnt;
> -ÂÂÂÂÂÂ unsigned char spdif_status_bits[SAI_IEC60958_STATUS_BYTES];
> +ÂÂÂÂÂÂ struct snd_aes_iec958 iec958;
> Â};
> Â
> Âenum stm32_sai_fifo_th {
> @@ -184,10 +185,6 @@ static bool stm32_sai_sub_writeable_reg(struct
> device *dev, unsigned int reg)
> ÂÂÂÂÂÂÂÂ }
> Â}
> Â
> -static const unsigned char
> default_status_bits[SAI_IEC60958_STATUS_BYTES] = {
> -ÂÂÂÂÂÂ 0, 0, 0, IEC958_AES3_CON_FS_48000,
> -};
> -
> Âstatic const struct regmap_config stm32_sai_sub_regmap_config_f4 = {
> ÂÂÂÂÂÂÂÂ .reg_bits = 32,
> ÂÂÂÂÂÂÂÂ .reg_stride = 4,
> @@ -619,6 +616,59 @@ static void stm32_sai_set_frame(struct snd_soc_dai
> *cpu_dai)
> ÂÂÂÂÂÂÂÂ }
> Â}
> Â
> +static void stm32_sai_set_channel_status(struct stm32_sai_sub_data *sai,
> +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂ struct snd_pcm_runtime *runtime)
> +{
> +ÂÂÂÂÂÂ if (!runtime)
> +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂ return;
> +
> +ÂÂÂÂÂÂ /* Force the sample rate according to runtime rate */
> +ÂÂÂÂÂÂ switch (runtime->rate) {
> +ÂÂÂÂÂÂ case 22050:
> +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂ sai->iec958.status[3] = IEC958_AES3_CON_FS_22050;
> +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂ break;
> +ÂÂÂÂÂÂ case 44100:
> +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂ sai->iec958.status[3] = IEC958_AES3_CON_FS_44100;
> +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂ break;
> +ÂÂÂÂÂÂ case 88200:
> +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂ sai->iec958.status[3] = IEC958_AES3_CON_FS_88200;
> +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂ break;
> +ÂÂÂÂÂÂ case 176400:
> +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂ sai->iec958.status[3] = IEC958_AES3_CON_FS_176400;
> +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂ break;
> +ÂÂÂÂÂÂ case 24000:
> +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂ sai->iec958.status[3] = IEC958_AES3_CON_FS_24000;
> +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂ break;
> +ÂÂÂÂÂÂ case 48000:
> +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂ sai->iec958.status[3] = IEC958_AES3_CON_FS_48000;
> +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂ break;
> +ÂÂÂÂÂÂ case 96000:
> +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂ sai->iec958.status[3] = IEC958_AES3_CON_FS_96000;
> +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂ break;
> +ÂÂÂÂÂÂ case 192000:
> +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂ sai->iec958.status[3] = IEC958_AES3_CON_FS_192000;
> +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂ break;
> +ÂÂÂÂÂÂ case 32000:
> +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂ sai->iec958.status[3] = IEC958_AES3_CON_FS_32000;
> +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂ break;
> +ÂÂÂÂÂÂ default:
> +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂ sai->iec958.status[3] = IEC958_AES3_CON_FS_NOTID;
> +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂ break;
> +ÂÂÂÂÂÂ }
> +}
> +
> +static int stm32_sai_iec958_set(struct snd_pcm_iec958_params *iec_param)
> +{
> +ÂÂÂÂÂÂ struct stm32_sai_sub_data *sai = iec_param->private_data;
> +
> +ÂÂÂÂÂÂ if (!sai->substream)
> +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂ return 0;
> +
> +ÂÂÂÂÂÂ stm32_sai_set_channel_status(sai, sai->substream->runtime);
> +
> +ÂÂÂÂÂÂ return 0;
> +}
> +
> Âstatic int stm32_sai_configure_clock(struct snd_soc_dai *cpu_dai,
> ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂ struct snd_pcm_hw_params *params)
> Â{
> @@ -709,7 +759,11 @@ static int stm32_sai_hw_params(struct
> snd_pcm_substream *substream,
> Â
> ÂÂÂÂÂÂÂÂ sai->data_size = params_width(params);
> Â
> -ÂÂÂÂÂÂ if (!STM_SAI_PROTOCOL_IS_SPDIF(sai)) {
> +ÂÂÂÂÂÂ if (STM_SAI_PROTOCOL_IS_SPDIF(sai)) {
> +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂ /* Rate not already set in runtime structure */
> +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂ substream->runtime->rate = params_rate(params);
> +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂ stm32_sai_set_channel_status(sai, substream->runtime);
> +ÂÂÂÂÂÂ } else {
> ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂ ret = stm32_sai_set_slots(cpu_dai);
> ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂ if (ret < 0)
> ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂ return ret;
> @@ -789,6 +843,28 @@ static void stm32_sai_shutdown(struct
> snd_pcm_substream *substream,
> ÂÂÂÂÂÂÂÂ sai->substream = NULL;
> Â}
> Â
> +static int stm32_sai_pcm_new(struct snd_soc_pcm_runtime *rtd,
> +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂ struct snd_soc_dai *cpu_dai)
> +{
> +ÂÂÂÂÂÂ struct stm32_sai_sub_data *sai = dev_get_drvdata(cpu_dai->dev);
> +ÂÂÂÂÂÂ struct snd_pcm_iec958_params *iec_param;
> +
> +ÂÂÂÂÂÂ if (STM_SAI_PROTOCOL_IS_SPDIF(sai)) {
> +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂ dev_dbg(&sai->pdev->dev, "%s: register iec controls",
> __func__);
> +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂ iec_param = devm_kzalloc(&sai->pdev->dev,
> sizeof(*iec_param),
> +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂ GFP_KERNEL);
> +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂ iec_param->ctrl_set = stm32_sai_iec958_set;
> +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂ iec_param->private_data = sai;
> +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂ iec_param->cs = sai->iec958.status;
> +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂ iec_param->cs_len = 5;
> +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂ return snd_pcm_add_iec958_ctl(rtd->pcm, 0,
> +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂ SNDRV_PCM_STREAM_PLAYBACK,
> +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂ iec_param);
> +ÂÂÂÂÂÂ }
> +
> +ÂÂÂÂÂÂ return 0;
> +}
> +
> Âstatic int stm32_sai_dai_probe(struct snd_soc_dai *cpu_dai)
> Â{
> ÂÂÂÂÂÂÂÂ struct stm32_sai_sub_data *sai = dev_get_drvdata(cpu_dai->dev);
> @@ -809,6 +885,10 @@ static int stm32_sai_dai_probe(struct snd_soc_dai
> *cpu_dai)
> ÂÂÂÂÂÂÂÂ else
> ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂ snd_soc_dai_init_dma_data(cpu_dai, NULL, &sai->dma_params);
> Â
> +ÂÂÂÂÂÂ /* Next settings are not relevant for spdif mode */
> +ÂÂÂÂÂÂ if (STM_SAI_PROTOCOL_IS_SPDIF(sai))
> +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂ return 0;
> +
> ÂÂÂÂÂÂÂÂ cr1_mask = SAI_XCR1_RX_TX;
> ÂÂÂÂÂÂÂÂ if (STM_SAI_IS_CAPTURE(sai))
> ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂ cr1 |= SAI_XCR1_RX_TX;
> @@ -820,10 +900,6 @@ static int stm32_sai_dai_probe(struct snd_soc_dai
> *cpu_dai)
> ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂ sai->synco, sai->synci);
> ÂÂÂÂÂÂÂÂ }
> Â
> -ÂÂÂÂÂÂ if (STM_SAI_PROTOCOL_IS_SPDIF(sai))
> -ÂÂÂÂÂÂÂÂÂÂÂÂÂÂ memcpy(sai->spdif_status_bits, default_status_bits,
> -ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂ sizeof(default_status_bits));
> -
> ÂÂÂÂÂÂÂÂ cr1_mask |= SAI_XCR1_SYNCEN_MASK;
> ÂÂÂÂÂÂÂÂ cr1 |= SAI_XCR1_SYNCEN_SET(sai->sync);
> Â
> @@ -861,7 +937,7 @@ static int stm32_sai_pcm_process_spdif(struct
> snd_pcm_substream *substream,
> ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂ /* Set channel status bit */
> ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂ byte = frm_cnt >> 3;
> ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂ mask = 1 << (frm_cnt - (byte << 3));
> -ÂÂÂÂÂÂÂÂÂÂÂÂÂÂ if (sai->spdif_status_bits[byte] & mask)
> +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂ if (sai->iec958.status[byte] & mask)
> ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂ *ptr |= 0x04000000;
> ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂ ptr++;
> Â
> @@ -888,6 +964,7 @@ static int stm32_sai_pcm_process_spdif(struct
> snd_pcm_substream *substream,
> Âstatic struct snd_soc_dai_driver stm32_sai_playback_dai[] = {
> Â{
> ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂ .probe = stm32_sai_dai_probe,
> +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂ .pcm_new = stm32_sai_pcm_new,
> ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂ .id = 1, /* avoid call to fmt_single_name() */
> ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂ .playback = {
> ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂ .channels_min = 1,
> --
> 1.9.1
>