summaryrefslogtreecommitdiff
path: root/sound/soc/tegra/tegra_asoc_machine.c
diff options
context:
space:
mode:
authorDmitry Osipenko <digetx@gmail.com>2021-05-29 18:46:49 +0300
committerMark Brown <broonie@kernel.org>2021-06-15 13:43:12 +0300
commit8c1b3b159300cc5ef6ba0d4b039ef68e766d46e3 (patch)
treec805229c2b77e82ab4ea102820dc834aedaf6fef /sound/soc/tegra/tegra_asoc_machine.c
parentc16aab8ddc645f129880a266c1626b07b41f7c55 (diff)
downloadlinux-8c1b3b159300cc5ef6ba0d4b039ef68e766d46e3.tar.xz
ASoC: tegra: Squash utils into common machine driver
There no users left of the utils other than the new common machine driver. Squash the utils into the common machine driver in order to simplify code. Signed-off-by: Dmitry Osipenko <digetx@gmail.com> Link: https://lore.kernel.org/r/20210529154649.25936-5-digetx@gmail.com Signed-off-by: Mark Brown <broonie@kernel.org>
Diffstat (limited to 'sound/soc/tegra/tegra_asoc_machine.c')
-rw-r--r--sound/soc/tegra/tegra_asoc_machine.c153
1 files changed, 144 insertions, 9 deletions
diff --git a/sound/soc/tegra/tegra_asoc_machine.c b/sound/soc/tegra/tegra_asoc_machine.c
index 31ab7123945b..a53aec361a77 100644
--- a/sound/soc/tegra/tegra_asoc_machine.c
+++ b/sound/soc/tegra/tegra_asoc_machine.c
@@ -3,6 +3,7 @@
* tegra_asoc_machine.c - Universal ASoC machine driver for NVIDIA Tegra boards.
*/
+#include <linux/clk.h>
#include <linux/export.h>
#include <linux/gpio/consumer.h>
#include <linux/module.h>
@@ -239,12 +240,68 @@ static int tegra_machine_hw_params(struct snd_pcm_substream *substream,
unsigned int srate = params_rate(params);
unsigned int mclk = machine->asoc->mclk_rate(srate);
unsigned int clk_id = machine->asoc->mclk_id;
+ unsigned int new_baseclock;
int err;
- err = tegra_asoc_utils_set_rate(&machine->util_data, srate, mclk);
- if (err < 0) {
- dev_err(card->dev, "Can't configure clocks: %d\n", err);
- return err;
+ switch (srate) {
+ case 11025:
+ case 22050:
+ case 44100:
+ case 88200:
+ if (of_machine_is_compatible("nvidia,tegra20"))
+ new_baseclock = 56448000;
+ else if (of_machine_is_compatible("nvidia,tegra30"))
+ new_baseclock = 564480000;
+ else
+ new_baseclock = 282240000;
+ break;
+ case 8000:
+ case 16000:
+ case 32000:
+ case 48000:
+ case 64000:
+ case 96000:
+ if (of_machine_is_compatible("nvidia,tegra20"))
+ new_baseclock = 73728000;
+ else if (of_machine_is_compatible("nvidia,tegra30"))
+ new_baseclock = 552960000;
+ else
+ new_baseclock = 368640000;
+ break;
+ default:
+ dev_err(card->dev, "Invalid sound rate: %u\n", srate);
+ return -EINVAL;
+ }
+
+ if (new_baseclock != machine->set_baseclock ||
+ mclk != machine->set_mclk) {
+ machine->set_baseclock = 0;
+ machine->set_mclk = 0;
+
+ clk_disable_unprepare(machine->clk_cdev1);
+
+ err = clk_set_rate(machine->clk_pll_a, new_baseclock);
+ if (err) {
+ dev_err(card->dev, "Can't set pll_a rate: %d\n", err);
+ return err;
+ }
+
+ err = clk_set_rate(machine->clk_pll_a_out0, mclk);
+ if (err) {
+ dev_err(card->dev, "Can't set pll_a_out0 rate: %d\n", err);
+ return err;
+ }
+
+ /* Don't set cdev1/extern1 rate; it's locked to pll_a_out0 */
+
+ err = clk_prepare_enable(machine->clk_cdev1);
+ if (err) {
+ dev_err(card->dev, "Can't enable cdev1: %d\n", err);
+ return err;
+ }
+
+ machine->set_baseclock = new_baseclock;
+ machine->set_mclk = mclk;
}
err = snd_soc_dai_set_sysclk(codec_dai, clk_id, mclk, SND_SOC_CLOCK_IN);
@@ -377,14 +434,92 @@ int tegra_asoc_machine_probe(struct platform_device *pdev)
if (!card->driver_name)
card->driver_name = "tegra";
- err = tegra_asoc_utils_init(&machine->util_data, &pdev->dev);
- if (err)
- return err;
+ machine->clk_pll_a = devm_clk_get(dev, "pll_a");
+ if (IS_ERR(machine->clk_pll_a)) {
+ dev_err(dev, "Can't retrieve clk pll_a\n");
+ return PTR_ERR(machine->clk_pll_a);
+ }
+
+ machine->clk_pll_a_out0 = devm_clk_get(dev, "pll_a_out0");
+ if (IS_ERR(machine->clk_pll_a_out0)) {
+ dev_err(dev, "Can't retrieve clk pll_a_out0\n");
+ return PTR_ERR(machine->clk_pll_a_out0);
+ }
+
+ machine->clk_cdev1 = devm_clk_get(dev, "mclk");
+ if (IS_ERR(machine->clk_cdev1)) {
+ dev_err(dev, "Can't retrieve clk cdev1\n");
+ return PTR_ERR(machine->clk_cdev1);
+ }
+
+ /*
+ * If clock parents are not set in DT, configure here to use clk_out_1
+ * as mclk and extern1 as parent for Tegra30 and higher.
+ */
+ if (!of_find_property(dev->of_node, "assigned-clock-parents", NULL) &&
+ !of_machine_is_compatible("nvidia,tegra20")) {
+ struct clk *clk_out_1, *clk_extern1;
+
+ dev_warn(dev, "Configuring clocks for a legacy device-tree\n");
+ dev_warn(dev, "Please update DT to use assigned-clock-parents\n");
+
+ clk_extern1 = devm_clk_get(dev, "extern1");
+ if (IS_ERR(clk_extern1)) {
+ dev_err(dev, "Can't retrieve clk extern1\n");
+ return PTR_ERR(clk_extern1);
+ }
+
+ err = clk_set_parent(clk_extern1, machine->clk_pll_a_out0);
+ if (err < 0) {
+ dev_err(dev, "Set parent failed for clk extern1\n");
+ return err;
+ }
+
+ clk_out_1 = devm_clk_get(dev, "pmc_clk_out_1");
+ if (IS_ERR(clk_out_1)) {
+ dev_err(dev, "Can't retrieve pmc_clk_out_1\n");
+ return PTR_ERR(clk_out_1);
+ }
+
+ err = clk_set_parent(clk_out_1, clk_extern1);
+ if (err < 0) {
+ dev_err(dev, "Set parent failed for pmc_clk_out_1\n");
+ return err;
+ }
+
+ machine->clk_cdev1 = clk_out_1;
+ }
if (asoc->set_ac97) {
- err = tegra_asoc_utils_set_ac97_rate(&machine->util_data);
- if (err)
+ /*
+ * AC97 rate is fixed at 24.576MHz and is used for both the
+ * host controller and the external codec
+ */
+ err = clk_set_rate(machine->clk_pll_a, 73728000);
+ if (err) {
+ dev_err(dev, "Can't set pll_a rate: %d\n", err);
return err;
+ }
+
+ err = clk_set_rate(machine->clk_pll_a_out0, 24576000);
+ if (err) {
+ dev_err(dev, "Can't set pll_a_out0 rate: %d\n", err);
+ return err;
+ }
+
+ machine->set_baseclock = 73728000;
+ machine->set_mclk = 24576000;
+ }
+
+ /*
+ * FIXME: There is some unknown dependency between audio MCLK disable
+ * and suspend-resume functionality on Tegra30, although audio MCLK is
+ * only needed for audio.
+ */
+ err = clk_prepare_enable(machine->clk_cdev1);
+ if (err) {
+ dev_err(dev, "Can't enable cdev1: %d\n", err);
+ return err;
}
err = devm_snd_soc_register_card(dev, card);