Re: [PATCH v5 3/6] ASoC: tegra: Add audio graph based card driver
From: Jon Hunter
Date: Mon Nov 23 2020 - 05:36:41 EST
On 11/11/2020 18:34, Sameer Pujar wrote:
> Add Tegra audio machine driver which is based on generic audio graph card
> driver. It re-uses most of the common stuff from audio graph driver and
> uses the same DT binding. Required Tegra specific customizations are done
> in the driver and additional DT bindings are required for clock handling.
>
> Details on the customizations done:
>
> - Update PLL rates at runtime: Tegra HW supports multiple sample rates
> (multiples of 8x and 11.025x) and both of these groups require different
> PLL rates. Hence there is a requirement to update this at runtime.
> This is achieved by providing a custom 'snd_soc_ops' and in hw_param()
> callback PLL rate is updated as per the sample rate.
>
> - Internal structure 'tegra_audio_graph_data' is used to maintain clock
> handles of PLL.
>
> - The 'force_dpcm' flag is set to use DPCM for all DAI links.
>
> - The 'component_chaining' flag is set to use DPCM with component model.
>
> Signed-off-by: Sameer Pujar <spujar@xxxxxxxxxx>
> ---
> sound/soc/tegra/Kconfig | 9 ++
> sound/soc/tegra/Makefile | 2 +
> sound/soc/tegra/tegra_audio_graph_card.c | 255 +++++++++++++++++++++++++++++++
> 3 files changed, 266 insertions(+)
> create mode 100644 sound/soc/tegra/tegra_audio_graph_card.c
>
> diff --git a/sound/soc/tegra/Kconfig b/sound/soc/tegra/Kconfig
> index a62cc87..6dc83ad 100644
> --- a/sound/soc/tegra/Kconfig
> +++ b/sound/soc/tegra/Kconfig
> @@ -117,6 +117,15 @@ config SND_SOC_TEGRA210_ADMAIF
> channel. Buffer size is configurable for each ADMAIIF channel.
> Say Y or M if you want to add support for Tegra210 ADMAIF module.
>
> +config SND_SOC_TEGRA_AUDIO_GRAPH_CARD
> + tristate "Audio Graph Card based Tegra driver"
> + depends on SND_AUDIO_GRAPH_CARD
> + help
> + Config to enable Tegra audio machine driver based on generic
> + audio graph driver. It is a thin driver written to customize
> + few things for Tegra audio. Most of the code is re-used from
> + audio graph driver and the same DT bindings are used.
> +
> config SND_SOC_TEGRA_RT5640
> tristate "SoC Audio support for Tegra boards using an RT5640 codec"
> depends on SND_SOC_TEGRA && I2C && GPIOLIB
> diff --git a/sound/soc/tegra/Makefile b/sound/soc/tegra/Makefile
> index 60040a0..b17dd6e 100644
> --- a/sound/soc/tegra/Makefile
> +++ b/sound/soc/tegra/Makefile
> @@ -38,6 +38,7 @@ snd-soc-tegra-trimslice-objs := trimslice.o
> snd-soc-tegra-alc5632-objs := tegra_alc5632.o
> snd-soc-tegra-max98090-objs := tegra_max98090.o
> snd-soc-tegra-sgtl5000-objs := tegra_sgtl5000.o
> +snd-soc-tegra-audio-graph-card-objs := tegra_audio_graph_card.o
>
> obj-$(CONFIG_SND_SOC_TEGRA_RT5640) += snd-soc-tegra-rt5640.o
> obj-$(CONFIG_SND_SOC_TEGRA_RT5677) += snd-soc-tegra-rt5677.o
> @@ -48,3 +49,4 @@ obj-$(CONFIG_SND_SOC_TEGRA_TRIMSLICE) += snd-soc-tegra-trimslice.o
> obj-$(CONFIG_SND_SOC_TEGRA_ALC5632) += snd-soc-tegra-alc5632.o
> obj-$(CONFIG_SND_SOC_TEGRA_MAX98090) += snd-soc-tegra-max98090.o
> obj-$(CONFIG_SND_SOC_TEGRA_SGTL5000) += snd-soc-tegra-sgtl5000.o
> +obj-$(CONFIG_SND_SOC_TEGRA_AUDIO_GRAPH_CARD) += snd-soc-tegra-audio-graph-card.o
> diff --git a/sound/soc/tegra/tegra_audio_graph_card.c b/sound/soc/tegra/tegra_audio_graph_card.c
> new file mode 100644
> index 0000000..f4d826d
> --- /dev/null
> +++ b/sound/soc/tegra/tegra_audio_graph_card.c
> @@ -0,0 +1,255 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +//
> +// tegra_audio_graph_card.c - Audio Graph based Tegra Machine Driver
> +//
> +// Copyright (c) 2020 NVIDIA CORPORATION. All rights reserved.
> +
> +#include <linux/math64.h>
> +#include <linux/module.h>
> +#include <linux/of_device.h>
> +#include <linux/platform_device.h>
> +#include <sound/graph_card.h>
> +#include <sound/pcm_params.h>
> +
> +#define MAX_PLLA_OUT0_DIV 128
> +
> +#define simple_to_tegra_priv(simple) \
> + container_of(simple, struct tegra_audio_priv, simple)
> +
> +enum srate_type {
> + /*
> + * Sample rates multiple of 8000 Hz and below are supported:
> + * ( 8000, 16000, 32000, 48000, 96000, 192000 Hz )
> + */
> + x8_RATE,
> +
> + /*
> + * Sample rates multiple of 11025 Hz and below are supported:
> + * ( 11025, 22050, 44100, 88200, 176400 Hz )
> + */
> + x11_RATE,
> +
> + NUM_RATE_TYPE,
> +};
> +
> +struct tegra_audio_priv {
> + struct asoc_simple_priv simple;
> + struct clk *clk_plla_out0;
> + struct clk *clk_plla;
> +};
> +
> +/* Tegra audio chip data */
> +struct tegra_audio_cdata {
> + unsigned int plla_rates[NUM_RATE_TYPE];
> + unsigned int plla_out0_rates[NUM_RATE_TYPE];
> +};
> +
> +/* Setup PLL clock as per the given sample rate */
> +static int tegra_audio_graph_update_pll(struct snd_pcm_substream *substream,
> + struct snd_pcm_hw_params *params)
> +{
> + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
> + struct asoc_simple_priv *simple = snd_soc_card_get_drvdata(rtd->card);
> + struct tegra_audio_priv *priv = simple_to_tegra_priv(simple);
> + struct device *dev = rtd->card->dev;
> + const struct tegra_audio_cdata *data = of_device_get_match_data(dev);
> + unsigned int plla_rate, plla_out0_rate, bclk;
> + unsigned int srate = params_rate(params);
> + int err;
> +
> + /* There is nothing to configure */
> + if (!data)
> + return 0;
Seems like this should never happen and so if it did this is an error.
Any reason why we don't return an error here?
Cheers
Jon
--
nvpublic