From: Dmitry Osipenko <digetx@gmail.com>
To: Thierry Reding <thierry.reding@gmail.com>,
Jonathan Hunter <jonathanh@nvidia.com>,
Mark Brown <broonie@kernel.org>, Takashi Iwai <tiwai@suse.com>,
Jaroslav Kysela <perex@perex.cz>,
Liam Girdwood <lgirdwood@gmail.com>, Agneli <poczt@protonmail.ch>,
Rob Herring <robh+dt@kernel.org>
Cc: linux-tegra@vger.kernel.org, devicetree@vger.kernel.org,
alsa-devel@alsa-project.org, linux-kernel@vger.kernel.org,
Arnd Bergmann <arnd@arndb.de>
Subject: [PATCH v1 13/20] ASoC: tegra20: i2s: Filter out unsupported rates
Date: Thu, 25 Nov 2021 01:00:50 +0300 [thread overview]
Message-ID: <20211124220057.15763-14-digetx@gmail.com> (raw)
In-Reply-To: <20211124220057.15763-1-digetx@gmail.com>
Support new nvidia,fixed-parent-rate device-tree property which instructs
I2S that board wants parent clock rate to stay at a fixed rate. This allows
to play audio over S/PDIF and I2S simultaneously. The root of the problem
is that audio components on Tegra share the same audio PLL, and thus, only
a subset of rates can be supported if we want to play audio simultaneously.
Filter out audio rates that don't match parent clock rate if device-tree
has the nvidia,fixed-parent-rate property.
Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
---
sound/soc/tegra/tegra20_i2s.c | 49 +++++++++++++++++++++++++++++++++++
1 file changed, 49 insertions(+)
diff --git a/sound/soc/tegra/tegra20_i2s.c b/sound/soc/tegra/tegra20_i2s.c
index 266d2cab9f49..27365a877e47 100644
--- a/sound/soc/tegra/tegra20_i2s.c
+++ b/sound/soc/tegra/tegra20_i2s.c
@@ -262,10 +262,59 @@ static int tegra20_i2s_probe(struct snd_soc_dai *dai)
return 0;
}
+static const unsigned int tegra20_i2s_rates[] = {
+ 8000, 11025, 16000, 22050, 32000, 44100, 48000, 64000, 88200, 96000
+};
+
+static int tegra20_i2s_filter_rates(struct snd_pcm_hw_params *params,
+ struct snd_pcm_hw_rule *rule)
+{
+ struct snd_interval *r = hw_param_interval(params, rule->var);
+ struct snd_soc_dai *dai = rule->private;
+ struct tegra20_i2s *i2s = dev_get_drvdata(dai->dev);
+ struct clk *parent = clk_get_parent(i2s->clk_i2s);
+ long i, parent_rate, valid_rates = 0;
+
+ parent_rate = clk_get_rate(parent);
+ if (parent_rate <= 0) {
+ dev_err(dai->dev, "Can't get parent clock rate: %ld\n",
+ parent_rate);
+ return parent_rate ?: -EINVAL;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(tegra20_i2s_rates); i++) {
+ if (parent_rate % (tegra20_i2s_rates[i] * 128) == 0)
+ valid_rates |= BIT(i);
+ }
+
+ /*
+ * At least one rate must be valid, otherwise the parent clock isn't
+ * audio PLL. Nothing should be filtered in this case.
+ */
+ if (!valid_rates)
+ valid_rates = BIT(ARRAY_SIZE(tegra20_i2s_rates)) - 1;
+
+ return snd_interval_list(r, ARRAY_SIZE(tegra20_i2s_rates),
+ tegra20_i2s_rates, valid_rates);
+}
+
+static int tegra20_i2s_startup(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+ if (!device_property_read_bool(dai->dev, "nvidia,fixed-parent-rate"))
+ return 0;
+
+ return snd_pcm_hw_rule_add(substream->runtime, 0,
+ SNDRV_PCM_HW_PARAM_RATE,
+ tegra20_i2s_filter_rates, dai,
+ SNDRV_PCM_HW_PARAM_RATE, -1);
+}
+
static const struct snd_soc_dai_ops tegra20_i2s_dai_ops = {
.set_fmt = tegra20_i2s_set_fmt,
.hw_params = tegra20_i2s_hw_params,
.trigger = tegra20_i2s_trigger,
+ .startup = tegra20_i2s_startup,
};
static const struct snd_soc_dai_driver tegra20_i2s_dai_template = {
--
2.33.1
WARNING: multiple messages have this Message-ID (diff)
From: Dmitry Osipenko <digetx@gmail.com>
To: Thierry Reding <thierry.reding@gmail.com>,
Jonathan Hunter <jonathanh@nvidia.com>,
Mark Brown <broonie@kernel.org>, Takashi Iwai <tiwai@suse.com>,
Jaroslav Kysela <perex@perex.cz>,
Liam Girdwood <lgirdwood@gmail.com>, Agneli <poczt@protonmail.ch>,
Rob Herring <robh+dt@kernel.org>
Cc: linux-tegra@vger.kernel.org, Arnd Bergmann <arnd@arndb.de>,
alsa-devel@alsa-project.org, linux-kernel@vger.kernel.org,
devicetree@vger.kernel.org
Subject: [PATCH v1 13/20] ASoC: tegra20: i2s: Filter out unsupported rates
Date: Thu, 25 Nov 2021 01:00:50 +0300 [thread overview]
Message-ID: <20211124220057.15763-14-digetx@gmail.com> (raw)
In-Reply-To: <20211124220057.15763-1-digetx@gmail.com>
Support new nvidia,fixed-parent-rate device-tree property which instructs
I2S that board wants parent clock rate to stay at a fixed rate. This allows
to play audio over S/PDIF and I2S simultaneously. The root of the problem
is that audio components on Tegra share the same audio PLL, and thus, only
a subset of rates can be supported if we want to play audio simultaneously.
Filter out audio rates that don't match parent clock rate if device-tree
has the nvidia,fixed-parent-rate property.
Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
---
sound/soc/tegra/tegra20_i2s.c | 49 +++++++++++++++++++++++++++++++++++
1 file changed, 49 insertions(+)
diff --git a/sound/soc/tegra/tegra20_i2s.c b/sound/soc/tegra/tegra20_i2s.c
index 266d2cab9f49..27365a877e47 100644
--- a/sound/soc/tegra/tegra20_i2s.c
+++ b/sound/soc/tegra/tegra20_i2s.c
@@ -262,10 +262,59 @@ static int tegra20_i2s_probe(struct snd_soc_dai *dai)
return 0;
}
+static const unsigned int tegra20_i2s_rates[] = {
+ 8000, 11025, 16000, 22050, 32000, 44100, 48000, 64000, 88200, 96000
+};
+
+static int tegra20_i2s_filter_rates(struct snd_pcm_hw_params *params,
+ struct snd_pcm_hw_rule *rule)
+{
+ struct snd_interval *r = hw_param_interval(params, rule->var);
+ struct snd_soc_dai *dai = rule->private;
+ struct tegra20_i2s *i2s = dev_get_drvdata(dai->dev);
+ struct clk *parent = clk_get_parent(i2s->clk_i2s);
+ long i, parent_rate, valid_rates = 0;
+
+ parent_rate = clk_get_rate(parent);
+ if (parent_rate <= 0) {
+ dev_err(dai->dev, "Can't get parent clock rate: %ld\n",
+ parent_rate);
+ return parent_rate ?: -EINVAL;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(tegra20_i2s_rates); i++) {
+ if (parent_rate % (tegra20_i2s_rates[i] * 128) == 0)
+ valid_rates |= BIT(i);
+ }
+
+ /*
+ * At least one rate must be valid, otherwise the parent clock isn't
+ * audio PLL. Nothing should be filtered in this case.
+ */
+ if (!valid_rates)
+ valid_rates = BIT(ARRAY_SIZE(tegra20_i2s_rates)) - 1;
+
+ return snd_interval_list(r, ARRAY_SIZE(tegra20_i2s_rates),
+ tegra20_i2s_rates, valid_rates);
+}
+
+static int tegra20_i2s_startup(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+ if (!device_property_read_bool(dai->dev, "nvidia,fixed-parent-rate"))
+ return 0;
+
+ return snd_pcm_hw_rule_add(substream->runtime, 0,
+ SNDRV_PCM_HW_PARAM_RATE,
+ tegra20_i2s_filter_rates, dai,
+ SNDRV_PCM_HW_PARAM_RATE, -1);
+}
+
static const struct snd_soc_dai_ops tegra20_i2s_dai_ops = {
.set_fmt = tegra20_i2s_set_fmt,
.hw_params = tegra20_i2s_hw_params,
.trigger = tegra20_i2s_trigger,
+ .startup = tegra20_i2s_startup,
};
static const struct snd_soc_dai_driver tegra20_i2s_dai_template = {
--
2.33.1
next prev parent reply other threads:[~2021-11-24 22:10 UTC|newest]
Thread overview: 60+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-11-24 22:00 [PATCH v1 00/20] Support HDMI audio on NVIDIA Tegra20 Dmitry Osipenko
2021-11-24 22:00 ` Dmitry Osipenko
2021-11-24 22:00 ` [PATCH v1 01/20] ASoC: dt-bindings: Add binding for Tegra20 S/PDIF Dmitry Osipenko
2021-11-24 22:00 ` Dmitry Osipenko
2021-11-24 22:00 ` [PATCH v1 02/20] ASoC: dt-bindings: tegra20-i2s: Convert to schema Dmitry Osipenko
2021-11-24 22:00 ` Dmitry Osipenko
2021-11-25 21:26 ` Rob Herring
2021-11-25 21:26 ` Rob Herring
2021-11-26 1:08 ` Dmitry Osipenko
2021-11-26 1:08 ` Dmitry Osipenko
2021-11-24 22:00 ` [PATCH v1 03/20] ASoC: dt-bindings: tegra20-i2s: Document new nvidia, fixed-parent-rate property Dmitry Osipenko
2021-11-24 22:00 ` [PATCH v1 03/20] ASoC: dt-bindings: tegra20-i2s: Document new nvidia,fixed-parent-rate property Dmitry Osipenko
2021-11-24 22:00 ` [PATCH v1 04/20] dt-bindings: host1x: Document optional HDMI sound-dai-cells Dmitry Osipenko
2021-11-24 22:00 ` Dmitry Osipenko
2021-11-24 22:00 ` [PATCH v1 05/20] ASoC: tegra20-spdif: stop setting slave_id Dmitry Osipenko
2021-11-24 22:00 ` Dmitry Osipenko
2021-11-24 22:00 ` [PATCH v1 06/20] ASoC: tegra20: spdif: Support device-tree Dmitry Osipenko
2021-11-24 22:00 ` Dmitry Osipenko
2021-11-24 22:00 ` [PATCH v1 07/20] ASoC: tegra20: spdif: Set FIFO trigger level Dmitry Osipenko
2021-11-24 22:00 ` Dmitry Osipenko
2021-11-25 12:02 ` Mark Brown
2021-11-25 12:02 ` Mark Brown
2021-11-25 12:04 ` Dmitry Osipenko
2021-11-25 12:04 ` Dmitry Osipenko
2021-11-25 12:28 ` Mark Brown
2021-11-25 12:28 ` Mark Brown
2021-11-25 12:53 ` Dmitry Osipenko
2021-11-25 12:53 ` Dmitry Osipenko
2021-11-25 13:18 ` Mark Brown
2021-11-25 13:18 ` Mark Brown
2021-11-25 13:36 ` Dmitry Osipenko
2021-11-25 13:36 ` Dmitry Osipenko
2021-11-24 22:00 ` [PATCH v1 08/20] ASoC: tegra20: spdif: Improve driver's code Dmitry Osipenko
2021-11-24 22:00 ` Dmitry Osipenko
2021-11-24 22:00 ` [PATCH v1 09/20] ASoC: tegra20: spdif: Use more resource-managed helpers Dmitry Osipenko
2021-11-24 22:00 ` Dmitry Osipenko
2021-11-24 22:00 ` [PATCH v1 10/20] ASoC: tegra20: spdif: Reset hardware Dmitry Osipenko
2021-11-24 22:00 ` Dmitry Osipenko
2021-11-24 22:00 ` [PATCH v1 11/20] ASoC: tegra20: spdif: Support system suspend Dmitry Osipenko
2021-11-24 22:00 ` Dmitry Osipenko
2021-11-24 22:00 ` [PATCH v1 12/20] ASoC: tegra20: spdif: Filter out unsupported rates Dmitry Osipenko
2021-11-24 22:00 ` Dmitry Osipenko
2021-11-24 22:00 ` Dmitry Osipenko [this message]
2021-11-24 22:00 ` [PATCH v1 13/20] ASoC: tegra20: i2s: " Dmitry Osipenko
2021-11-24 22:00 ` [PATCH v1 14/20] drm/tegra: hdmi: Unwind tegra_hdmi_init() errors Dmitry Osipenko
2021-11-24 22:00 ` Dmitry Osipenko
2021-11-24 22:00 ` [PATCH v1 15/20] drm/tegra: hdmi: Register audio CODEC on Tegra20 Dmitry Osipenko
2021-11-24 22:00 ` Dmitry Osipenko
2021-11-24 22:00 ` [PATCH v1 16/20] ARM: tegra_defconfig: Enable S/PDIF driver Dmitry Osipenko
2021-11-24 22:00 ` Dmitry Osipenko
2021-11-24 22:00 ` [PATCH v1 17/20] ARM: tegra: Add S/PDIF node to Tegra20 device-tree Dmitry Osipenko
2021-11-24 22:00 ` Dmitry Osipenko
2021-11-25 11:43 ` Dmitry Osipenko
2021-11-25 11:43 ` Dmitry Osipenko
2021-11-24 22:00 ` [PATCH v1 18/20] ARM: tegra: Add HDMI audio graph " Dmitry Osipenko
2021-11-24 22:00 ` Dmitry Osipenko
2021-11-24 22:00 ` [PATCH v1 19/20] ARM: tegra: acer-a500: Enable S/PDIF and HDMI audio Dmitry Osipenko
2021-11-24 22:00 ` Dmitry Osipenko
2021-11-24 22:00 ` [PATCH v1 20/20] ARM: tegra: paz00: " Dmitry Osipenko
2021-11-24 22:00 ` Dmitry Osipenko
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20211124220057.15763-14-digetx@gmail.com \
--to=digetx@gmail.com \
--cc=alsa-devel@alsa-project.org \
--cc=arnd@arndb.de \
--cc=broonie@kernel.org \
--cc=devicetree@vger.kernel.org \
--cc=jonathanh@nvidia.com \
--cc=lgirdwood@gmail.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-tegra@vger.kernel.org \
--cc=perex@perex.cz \
--cc=poczt@protonmail.ch \
--cc=robh+dt@kernel.org \
--cc=thierry.reding@gmail.com \
--cc=tiwai@suse.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.