summaryrefslogtreecommitdiff
path: root/sound/soc/tegra
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/tegra')
-rw-r--r--sound/soc/tegra/Kconfig1
-rw-r--r--sound/soc/tegra/Makefile46
-rw-r--r--sound/soc/tegra/tegra186_asrc.c33
-rw-r--r--sound/soc/tegra/tegra186_asrc.h12
-rw-r--r--sound/soc/tegra/tegra186_dspk.c25
-rw-r--r--sound/soc/tegra/tegra20_ac97.c2
-rw-r--r--sound/soc/tegra/tegra20_i2s.c15
-rw-r--r--sound/soc/tegra/tegra20_spdif.c13
-rw-r--r--sound/soc/tegra/tegra210_admaif.c271
-rw-r--r--sound/soc/tegra/tegra210_admaif.h87
-rw-r--r--sound/soc/tegra/tegra210_adx.c257
-rw-r--r--sound/soc/tegra/tegra210_adx.h36
-rw-r--r--sound/soc/tegra/tegra210_ahub.c873
-rw-r--r--sound/soc/tegra/tegra210_ahub.h52
-rw-r--r--sound/soc/tegra/tegra210_amx.c251
-rw-r--r--sound/soc/tegra/tegra210_amx.h34
-rw-r--r--sound/soc/tegra/tegra210_dmic.c22
-rw-r--r--sound/soc/tegra/tegra210_i2s.c345
-rw-r--r--sound/soc/tegra/tegra210_i2s.h60
-rw-r--r--sound/soc/tegra/tegra210_mixer.c24
-rw-r--r--sound/soc/tegra/tegra210_mvc.c24
-rw-r--r--sound/soc/tegra/tegra210_ope.c24
-rw-r--r--sound/soc/tegra/tegra210_sfc.c24
-rw-r--r--sound/soc/tegra/tegra30_ahub.c15
-rw-r--r--sound/soc/tegra/tegra30_i2s.c15
-rw-r--r--sound/soc/tegra/tegra_asoc_machine.c20
-rw-r--r--sound/soc/tegra/tegra_audio_graph_card.c16
-rw-r--r--sound/soc/tegra/tegra_cif.h30
-rw-r--r--sound/soc/tegra/tegra_isomgr_bw.c130
-rw-r--r--sound/soc/tegra/tegra_isomgr_bw.h31
-rw-r--r--sound/soc/tegra/tegra_pcm.c8
-rw-r--r--sound/soc/tegra/tegra_wm8903.c2
32 files changed, 2438 insertions, 360 deletions
diff --git a/sound/soc/tegra/Kconfig b/sound/soc/tegra/Kconfig
index 74effc57a7a0..2463c22e9cf6 100644
--- a/sound/soc/tegra/Kconfig
+++ b/sound/soc/tegra/Kconfig
@@ -78,6 +78,7 @@ config SND_SOC_TEGRA210_DMIC
config SND_SOC_TEGRA210_I2S
tristate "Tegra210 I2S module"
+ select SND_SIMPLE_CARD_UTILS
help
Config to enable the Inter-IC Sound (I2S) Controller which
implements full-duplex and bidirectional and single direction
diff --git a/sound/soc/tegra/Makefile b/sound/soc/tegra/Makefile
index b723c78e665d..defea7f53f11 100644
--- a/sound/soc/tegra/Makefile
+++ b/sound/soc/tegra/Makefile
@@ -1,25 +1,25 @@
# SPDX-License-Identifier: GPL-2.0
# Tegra platform Support
-snd-soc-tegra-pcm-objs := tegra_pcm.o
-snd-soc-tegra-utils-objs += tegra_asoc_utils.o
-snd-soc-tegra20-ac97-objs := tegra20_ac97.o
-snd-soc-tegra20-das-objs := tegra20_das.o
-snd-soc-tegra20-i2s-objs := tegra20_i2s.o
-snd-soc-tegra20-spdif-objs := tegra20_spdif.o
-snd-soc-tegra30-ahub-objs := tegra30_ahub.o
-snd-soc-tegra30-i2s-objs := tegra30_i2s.o
-snd-soc-tegra210-ahub-objs := tegra210_ahub.o
-snd-soc-tegra210-dmic-objs := tegra210_dmic.o
-snd-soc-tegra210-i2s-objs := tegra210_i2s.o
-snd-soc-tegra186-asrc-objs := tegra186_asrc.o
-snd-soc-tegra186-dspk-objs := tegra186_dspk.o
-snd-soc-tegra210-admaif-objs := tegra210_admaif.o
-snd-soc-tegra210-mvc-objs := tegra210_mvc.o
-snd-soc-tegra210-sfc-objs := tegra210_sfc.o
-snd-soc-tegra210-amx-objs := tegra210_amx.o
-snd-soc-tegra210-adx-objs := tegra210_adx.o
-snd-soc-tegra210-mixer-objs := tegra210_mixer.o
-snd-soc-tegra210-ope-objs := tegra210_ope.o tegra210_mbdrc.o tegra210_peq.o
+snd-soc-tegra-pcm-y := tegra_pcm.o
+snd-soc-tegra-utils-y += tegra_asoc_utils.o
+snd-soc-tegra20-ac97-y := tegra20_ac97.o
+snd-soc-tegra20-das-y := tegra20_das.o
+snd-soc-tegra20-i2s-y := tegra20_i2s.o
+snd-soc-tegra20-spdif-y := tegra20_spdif.o
+snd-soc-tegra30-ahub-y := tegra30_ahub.o
+snd-soc-tegra30-i2s-y := tegra30_i2s.o
+snd-soc-tegra210-ahub-y := tegra210_ahub.o
+snd-soc-tegra210-dmic-y := tegra210_dmic.o
+snd-soc-tegra210-i2s-y := tegra210_i2s.o
+snd-soc-tegra186-asrc-y := tegra186_asrc.o
+snd-soc-tegra186-dspk-y := tegra186_dspk.o
+snd-soc-tegra210-admaif-y := tegra210_admaif.o tegra_isomgr_bw.o
+snd-soc-tegra210-mvc-y := tegra210_mvc.o
+snd-soc-tegra210-sfc-y := tegra210_sfc.o
+snd-soc-tegra210-amx-y := tegra210_amx.o
+snd-soc-tegra210-adx-y := tegra210_adx.o
+snd-soc-tegra210-mixer-y := tegra210_mixer.o
+snd-soc-tegra210-ope-y := tegra210_ope.o tegra210_mbdrc.o tegra210_peq.o
obj-$(CONFIG_SND_SOC_TEGRA) += snd-soc-tegra-pcm.o
obj-$(CONFIG_SND_SOC_TEGRA20_AC97) += snd-soc-tegra20-ac97.o
@@ -42,9 +42,9 @@ obj-$(CONFIG_SND_SOC_TEGRA210_MIXER) += snd-soc-tegra210-mixer.o
obj-$(CONFIG_SND_SOC_TEGRA210_OPE) += snd-soc-tegra210-ope.o
# Tegra machine Support
-snd-soc-tegra-wm8903-objs := tegra_wm8903.o
-snd-soc-tegra-machine-objs := tegra_asoc_machine.o
-snd-soc-tegra-audio-graph-card-objs := tegra_audio_graph_card.o
+snd-soc-tegra-wm8903-y := tegra_wm8903.o
+snd-soc-tegra-machine-y := tegra_asoc_machine.o
+snd-soc-tegra-audio-graph-card-y := tegra_audio_graph_card.o
obj-$(CONFIG_SND_SOC_TEGRA_WM8903) += snd-soc-tegra-wm8903.o
obj-$(CONFIG_SND_SOC_TEGRA_MACHINE_DRV) += snd-soc-tegra-machine.o
diff --git a/sound/soc/tegra/tegra186_asrc.c b/sound/soc/tegra/tegra186_asrc.c
index 22af5135d77a..851509ae07f5 100644
--- a/sound/soc/tegra/tegra186_asrc.c
+++ b/sound/soc/tegra/tegra186_asrc.c
@@ -1,8 +1,7 @@
// SPDX-License-Identifier: GPL-2.0-only
+// SPDX-FileCopyrightText: Copyright (c) 2022-2025 NVIDIA CORPORATION. All rights reserved.
//
// tegra186_asrc.c - Tegra186 ASRC driver
-//
-// Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved.
#include <linux/clk.h>
#include <linux/delay.h>
@@ -76,7 +75,7 @@ static void tegra186_asrc_lock_stream(struct tegra186_asrc *asrc,
1);
}
-static int __maybe_unused tegra186_asrc_runtime_suspend(struct device *dev)
+static int tegra186_asrc_runtime_suspend(struct device *dev)
{
struct tegra186_asrc *asrc = dev_get_drvdata(dev);
@@ -86,7 +85,7 @@ static int __maybe_unused tegra186_asrc_runtime_suspend(struct device *dev)
return 0;
}
-static int __maybe_unused tegra186_asrc_runtime_resume(struct device *dev)
+static int tegra186_asrc_runtime_resume(struct device *dev)
{
struct tegra186_asrc *asrc = dev_get_drvdata(dev);
int id;
@@ -99,7 +98,7 @@ static int __maybe_unused tegra186_asrc_runtime_resume(struct device *dev)
* sync is done after this to restore other settings.
*/
regmap_write(asrc->regmap, TEGRA186_ASRC_GLOBAL_SCRATCH_ADDR,
- TEGRA186_ASRC_ARAM_START_ADDR);
+ asrc->soc_data->aram_start_addr);
regmap_write(asrc->regmap, TEGRA186_ASRC_GLOBAL_ENB,
TEGRA186_ASRC_GLOBAL_EN);
@@ -954,8 +953,17 @@ static const struct regmap_config tegra186_asrc_regmap_config = {
.cache_type = REGCACHE_FLAT,
};
+static const struct tegra_asrc_soc_data soc_data_tegra186 = {
+ .aram_start_addr = TEGRA186_ASRC_ARAM_START_ADDR,
+};
+
+static const struct tegra_asrc_soc_data soc_data_tegra264 = {
+ .aram_start_addr = TEGRA264_ASRC_ARAM_START_ADDR,
+};
+
static const struct of_device_id tegra186_asrc_of_match[] = {
- { .compatible = "nvidia,tegra186-asrc" },
+ { .compatible = "nvidia,tegra186-asrc", .data = &soc_data_tegra186 },
+ { .compatible = "nvidia,tegra264-asrc", .data = &soc_data_tegra264 },
{},
};
MODULE_DEVICE_TABLE(of, tegra186_asrc_of_match);
@@ -985,6 +993,8 @@ static int tegra186_asrc_platform_probe(struct platform_device *pdev)
return PTR_ERR(asrc->regmap);
}
+ asrc->soc_data = of_device_get_match_data(&pdev->dev);
+
regcache_cache_only(asrc->regmap, true);
regmap_write(asrc->regmap, TEGRA186_ASRC_GLOBAL_CFG,
@@ -1021,20 +1031,19 @@ static void tegra186_asrc_platform_remove(struct platform_device *pdev)
}
static const struct dev_pm_ops tegra186_asrc_pm_ops = {
- SET_RUNTIME_PM_OPS(tegra186_asrc_runtime_suspend,
- tegra186_asrc_runtime_resume, NULL)
- SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
- pm_runtime_force_resume)
+ RUNTIME_PM_OPS(tegra186_asrc_runtime_suspend,
+ tegra186_asrc_runtime_resume, NULL)
+ SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, pm_runtime_force_resume)
};
static struct platform_driver tegra186_asrc_driver = {
.driver = {
.name = "tegra186-asrc",
.of_match_table = tegra186_asrc_of_match,
- .pm = &tegra186_asrc_pm_ops,
+ .pm = pm_ptr(&tegra186_asrc_pm_ops),
},
.probe = tegra186_asrc_platform_probe,
- .remove_new = tegra186_asrc_platform_remove,
+ .remove = tegra186_asrc_platform_remove,
};
module_platform_driver(tegra186_asrc_driver)
diff --git a/sound/soc/tegra/tegra186_asrc.h b/sound/soc/tegra/tegra186_asrc.h
index 094fcc723c02..0c98e26d5e72 100644
--- a/sound/soc/tegra/tegra186_asrc.h
+++ b/sound/soc/tegra/tegra186_asrc.h
@@ -1,9 +1,7 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
+/* SPDX-License-Identifier: GPL-2.0-only
+ * SPDX-FileCopyrightText: Copyright (c) 2022-2024 NVIDIA CORPORATION. All rights reserved.
* tegra186_asrc.h - Definitions for Tegra186 ASRC driver
*
- * Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved.
- *
*/
#ifndef __TEGRA186_ASRC_H__
@@ -94,6 +92,7 @@
#define TEGRA186_ASRC_RATIO_SOURCE_SW 0x1
#define TEGRA186_ASRC_ARAM_START_ADDR 0x3f800000
+#define TEGRA264_ASRC_ARAM_START_ADDR 0x8a080000
struct tegra186_asrc_lane {
unsigned int int_part;
@@ -104,7 +103,12 @@ struct tegra186_asrc_lane {
unsigned int output_thresh;
};
+struct tegra_asrc_soc_data {
+ unsigned int aram_start_addr;
+};
+
struct tegra186_asrc {
+ const struct tegra_asrc_soc_data *soc_data;
struct tegra186_asrc_lane lane[TEGRA186_ASRC_STREAM_MAX];
struct regmap *regmap;
};
diff --git a/sound/soc/tegra/tegra186_dspk.c b/sound/soc/tegra/tegra186_dspk.c
index aa37c4ab0adb..21fdab2a1977 100644
--- a/sound/soc/tegra/tegra186_dspk.c
+++ b/sound/soc/tegra/tegra186_dspk.c
@@ -1,8 +1,7 @@
// SPDX-License-Identifier: GPL-2.0-only
+// SPDX-FileCopyrightText: Copyright (c) 2020-2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
//
// tegra186_dspk.c - Tegra186 DSPK driver
-//
-// Copyright (c) 2020 NVIDIA CORPORATION. All rights reserved.
#include <linux/clk.h>
#include <linux/device.h>
@@ -182,7 +181,7 @@ static int tegra186_dspk_put_stereo_to_mono(struct snd_kcontrol *kcontrol,
return 1;
}
-static int __maybe_unused tegra186_dspk_runtime_suspend(struct device *dev)
+static int tegra186_dspk_runtime_suspend(struct device *dev)
{
struct tegra186_dspk *dspk = dev_get_drvdata(dev);
@@ -194,7 +193,7 @@ static int __maybe_unused tegra186_dspk_runtime_suspend(struct device *dev)
return 0;
}
-static int __maybe_unused tegra186_dspk_runtime_resume(struct device *dev)
+static int tegra186_dspk_runtime_resume(struct device *dev)
{
struct tegra186_dspk *dspk = dev_get_drvdata(dev);
int err;
@@ -241,14 +240,15 @@ static int tegra186_dspk_hw_params(struct snd_pcm_substream *substream,
return -EINVAL;
}
- cif_conf.client_bits = TEGRA_ACIF_BITS_24;
-
switch (params_format(params)) {
case SNDRV_PCM_FORMAT_S16_LE:
cif_conf.audio_bits = TEGRA_ACIF_BITS_16;
+ cif_conf.client_bits = TEGRA_ACIF_BITS_16;
break;
+ case SNDRV_PCM_FORMAT_S24_LE:
case SNDRV_PCM_FORMAT_S32_LE:
cif_conf.audio_bits = TEGRA_ACIF_BITS_32;
+ cif_conf.client_bits = TEGRA_ACIF_BITS_24;
break;
default:
dev_err(dev, "unsupported format!\n");
@@ -314,6 +314,7 @@ static struct snd_soc_dai_driver tegra186_dspk_dais[] = {
.channels_max = 2,
.rates = SNDRV_PCM_RATE_8000_48000,
.formats = SNDRV_PCM_FMTBIT_S16_LE |
+ SNDRV_PCM_FMTBIT_S24_LE |
SNDRV_PCM_FMTBIT_S32_LE,
},
},
@@ -325,6 +326,7 @@ static struct snd_soc_dai_driver tegra186_dspk_dais[] = {
.channels_max = 2,
.rates = SNDRV_PCM_RATE_8000_48000,
.formats = SNDRV_PCM_FMTBIT_S16_LE |
+ SNDRV_PCM_FMTBIT_S24_LE |
SNDRV_PCM_FMTBIT_S32_LE,
},
.ops = &tegra186_dspk_dai_ops,
@@ -530,20 +532,19 @@ static void tegra186_dspk_platform_remove(struct platform_device *pdev)
}
static const struct dev_pm_ops tegra186_dspk_pm_ops = {
- SET_RUNTIME_PM_OPS(tegra186_dspk_runtime_suspend,
- tegra186_dspk_runtime_resume, NULL)
- SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
- pm_runtime_force_resume)
+ RUNTIME_PM_OPS(tegra186_dspk_runtime_suspend,
+ tegra186_dspk_runtime_resume, NULL)
+ SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, pm_runtime_force_resume)
};
static struct platform_driver tegra186_dspk_driver = {
.driver = {
.name = "tegra186-dspk",
.of_match_table = tegra186_dspk_of_match,
- .pm = &tegra186_dspk_pm_ops,
+ .pm = pm_ptr(&tegra186_dspk_pm_ops),
},
.probe = tegra186_dspk_platform_probe,
- .remove_new = tegra186_dspk_platform_remove,
+ .remove = tegra186_dspk_platform_remove,
};
module_platform_driver(tegra186_dspk_driver);
diff --git a/sound/soc/tegra/tegra20_ac97.c b/sound/soc/tegra/tegra20_ac97.c
index 8011afe93c96..08c58e8f3c22 100644
--- a/sound/soc/tegra/tegra20_ac97.c
+++ b/sound/soc/tegra/tegra20_ac97.c
@@ -448,7 +448,7 @@ static struct platform_driver tegra20_ac97_driver = {
.of_match_table = tegra20_ac97_of_match,
},
.probe = tegra20_ac97_platform_probe,
- .remove_new = tegra20_ac97_platform_remove,
+ .remove = tegra20_ac97_platform_remove,
};
module_platform_driver(tegra20_ac97_driver);
diff --git a/sound/soc/tegra/tegra20_i2s.c b/sound/soc/tegra/tegra20_i2s.c
index f11618e8f13e..51df0835ce3e 100644
--- a/sound/soc/tegra/tegra20_i2s.c
+++ b/sound/soc/tegra/tegra20_i2s.c
@@ -34,7 +34,7 @@
#define DRV_NAME "tegra20-i2s"
-static __maybe_unused int tegra20_i2s_runtime_suspend(struct device *dev)
+static int tegra20_i2s_runtime_suspend(struct device *dev)
{
struct tegra20_i2s *i2s = dev_get_drvdata(dev);
@@ -45,7 +45,7 @@ static __maybe_unused int tegra20_i2s_runtime_suspend(struct device *dev)
return 0;
}
-static __maybe_unused int tegra20_i2s_runtime_resume(struct device *dev)
+static int tegra20_i2s_runtime_resume(struct device *dev)
{
struct tegra20_i2s *i2s = dev_get_drvdata(dev);
int ret;
@@ -487,20 +487,19 @@ static const struct of_device_id tegra20_i2s_of_match[] = {
};
static const struct dev_pm_ops tegra20_i2s_pm_ops = {
- SET_RUNTIME_PM_OPS(tegra20_i2s_runtime_suspend,
- tegra20_i2s_runtime_resume, NULL)
- SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
- pm_runtime_force_resume)
+ RUNTIME_PM_OPS(tegra20_i2s_runtime_suspend,
+ tegra20_i2s_runtime_resume, NULL)
+ SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, pm_runtime_force_resume)
};
static struct platform_driver tegra20_i2s_driver = {
.driver = {
.name = DRV_NAME,
.of_match_table = tegra20_i2s_of_match,
- .pm = &tegra20_i2s_pm_ops,
+ .pm = pm_ptr(&tegra20_i2s_pm_ops),
},
.probe = tegra20_i2s_platform_probe,
- .remove_new = tegra20_i2s_platform_remove,
+ .remove = tegra20_i2s_platform_remove,
};
module_platform_driver(tegra20_i2s_driver);
diff --git a/sound/soc/tegra/tegra20_spdif.c b/sound/soc/tegra/tegra20_spdif.c
index 380011233eb1..38661d9b4a7c 100644
--- a/sound/soc/tegra/tegra20_spdif.c
+++ b/sound/soc/tegra/tegra20_spdif.c
@@ -25,7 +25,7 @@
#include "tegra20_spdif.h"
-static __maybe_unused int tegra20_spdif_runtime_suspend(struct device *dev)
+static int tegra20_spdif_runtime_suspend(struct device *dev)
{
struct tegra20_spdif *spdif = dev_get_drvdata(dev);
@@ -36,7 +36,7 @@ static __maybe_unused int tegra20_spdif_runtime_suspend(struct device *dev)
return 0;
}
-static __maybe_unused int tegra20_spdif_runtime_resume(struct device *dev)
+static int tegra20_spdif_runtime_resume(struct device *dev)
{
struct tegra20_spdif *spdif = dev_get_drvdata(dev);
int ret;
@@ -403,10 +403,9 @@ static int tegra20_spdif_platform_probe(struct platform_device *pdev)
}
static const struct dev_pm_ops tegra20_spdif_pm_ops = {
- SET_RUNTIME_PM_OPS(tegra20_spdif_runtime_suspend,
- tegra20_spdif_runtime_resume, NULL)
- SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
- pm_runtime_force_resume)
+ RUNTIME_PM_OPS(tegra20_spdif_runtime_suspend,
+ tegra20_spdif_runtime_resume, NULL)
+ SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, pm_runtime_force_resume)
};
static const struct of_device_id tegra20_spdif_of_match[] = {
@@ -418,7 +417,7 @@ MODULE_DEVICE_TABLE(of, tegra20_spdif_of_match);
static struct platform_driver tegra20_spdif_driver = {
.driver = {
.name = "tegra20-spdif",
- .pm = &tegra20_spdif_pm_ops,
+ .pm = pm_ptr(&tegra20_spdif_pm_ops),
.of_match_table = tegra20_spdif_of_match,
},
.probe = tegra20_spdif_platform_probe,
diff --git a/sound/soc/tegra/tegra210_admaif.c b/sound/soc/tegra/tegra210_admaif.c
index 9f9334e48049..f88d6a2356e0 100644
--- a/sound/soc/tegra/tegra210_admaif.c
+++ b/sound/soc/tegra/tegra210_admaif.c
@@ -1,8 +1,8 @@
// SPDX-License-Identifier: GPL-2.0-only
+// SPDX-FileCopyrightText: Copyright (c) 2020-2025 NVIDIA CORPORATION & AFFILIATES.
+// All rights reserved.
//
// tegra210_admaif.c - Tegra ADMAIF driver
-//
-// Copyright (c) 2020 NVIDIA CORPORATION. All rights reserved.
#include <linux/clk.h>
#include <linux/device.h>
@@ -13,6 +13,7 @@
#include <linux/regmap.h>
#include <sound/pcm_params.h>
#include <sound/soc.h>
+#include "tegra_isomgr_bw.h"
#include "tegra210_admaif.h"
#include "tegra_cif.h"
#include "tegra_pcm.h"
@@ -24,12 +25,12 @@
#define CH_RX_REG(reg, id) CH_REG(admaif->soc_data->rx_base, reg, id)
-#define REG_DEFAULTS(id, rx_ctrl, tx_ctrl, tx_base, rx_base) \
+#define REG_DEFAULTS(id, rx_ctrl, tx_ctrl, tx_base, rx_base, cif_ctrl) \
{ CH_REG(rx_base, TEGRA_ADMAIF_RX_INT_MASK, id), 0x00000001 }, \
- { CH_REG(rx_base, TEGRA_ADMAIF_CH_ACIF_RX_CTRL, id), 0x00007700 }, \
+ { CH_REG(rx_base, TEGRA_ADMAIF_CH_ACIF_RX_CTRL, id), cif_ctrl }, \
{ CH_REG(rx_base, TEGRA_ADMAIF_RX_FIFO_CTRL, id), rx_ctrl }, \
{ CH_REG(tx_base, TEGRA_ADMAIF_TX_INT_MASK, id), 0x00000001 }, \
- { CH_REG(tx_base, TEGRA_ADMAIF_CH_ACIF_TX_CTRL, id), 0x00007700 }, \
+ { CH_REG(tx_base, TEGRA_ADMAIF_CH_ACIF_TX_CTRL, id), cif_ctrl }, \
{ CH_REG(tx_base, TEGRA_ADMAIF_TX_FIFO_CTRL, id), tx_ctrl }
#define ADMAIF_REG_DEFAULTS(id, chip) \
@@ -37,7 +38,8 @@
chip ## _ADMAIF_RX ## id ## _FIFO_CTRL_REG_DEFAULT, \
chip ## _ADMAIF_TX ## id ## _FIFO_CTRL_REG_DEFAULT, \
chip ## _ADMAIF_TX_BASE, \
- chip ## _ADMAIF_RX_BASE)
+ chip ## _ADMAIF_RX_BASE, \
+ chip ## _ADMAIF_CIF_REG_DEFAULT)
static const struct reg_default tegra186_admaif_reg_defaults[] = {
{(TEGRA_ADMAIF_GLOBAL_CG_0 + TEGRA186_ADMAIF_GLOBAL_BASE), 0x00000003},
@@ -77,6 +79,42 @@ static const struct reg_default tegra210_admaif_reg_defaults[] = {
ADMAIF_REG_DEFAULTS(10, TEGRA210)
};
+static const struct reg_default tegra264_admaif_reg_defaults[] = {
+ {(TEGRA_ADMAIF_GLOBAL_CG_0 + TEGRA264_ADMAIF_GLOBAL_BASE), 0x00000003},
+ ADMAIF_REG_DEFAULTS(1, TEGRA264),
+ ADMAIF_REG_DEFAULTS(2, TEGRA264),
+ ADMAIF_REG_DEFAULTS(3, TEGRA264),
+ ADMAIF_REG_DEFAULTS(4, TEGRA264),
+ ADMAIF_REG_DEFAULTS(5, TEGRA264),
+ ADMAIF_REG_DEFAULTS(6, TEGRA264),
+ ADMAIF_REG_DEFAULTS(7, TEGRA264),
+ ADMAIF_REG_DEFAULTS(8, TEGRA264),
+ ADMAIF_REG_DEFAULTS(9, TEGRA264),
+ ADMAIF_REG_DEFAULTS(10, TEGRA264),
+ ADMAIF_REG_DEFAULTS(11, TEGRA264),
+ ADMAIF_REG_DEFAULTS(12, TEGRA264),
+ ADMAIF_REG_DEFAULTS(13, TEGRA264),
+ ADMAIF_REG_DEFAULTS(14, TEGRA264),
+ ADMAIF_REG_DEFAULTS(15, TEGRA264),
+ ADMAIF_REG_DEFAULTS(16, TEGRA264),
+ ADMAIF_REG_DEFAULTS(17, TEGRA264),
+ ADMAIF_REG_DEFAULTS(18, TEGRA264),
+ ADMAIF_REG_DEFAULTS(19, TEGRA264),
+ ADMAIF_REG_DEFAULTS(20, TEGRA264),
+ ADMAIF_REG_DEFAULTS(21, TEGRA264),
+ ADMAIF_REG_DEFAULTS(22, TEGRA264),
+ ADMAIF_REG_DEFAULTS(23, TEGRA264),
+ ADMAIF_REG_DEFAULTS(24, TEGRA264),
+ ADMAIF_REG_DEFAULTS(25, TEGRA264),
+ ADMAIF_REG_DEFAULTS(26, TEGRA264),
+ ADMAIF_REG_DEFAULTS(27, TEGRA264),
+ ADMAIF_REG_DEFAULTS(28, TEGRA264),
+ ADMAIF_REG_DEFAULTS(29, TEGRA264),
+ ADMAIF_REG_DEFAULTS(30, TEGRA264),
+ ADMAIF_REG_DEFAULTS(31, TEGRA264),
+ ADMAIF_REG_DEFAULTS(32, TEGRA264)
+};
+
static bool tegra_admaif_wr_reg(struct device *dev, unsigned int reg)
{
struct tegra_admaif *admaif = dev_get_drvdata(dev);
@@ -219,7 +257,20 @@ static const struct regmap_config tegra186_admaif_regmap_config = {
.cache_type = REGCACHE_FLAT,
};
-static int __maybe_unused tegra_admaif_runtime_suspend(struct device *dev)
+static const struct regmap_config tegra264_admaif_regmap_config = {
+ .reg_bits = 32,
+ .reg_stride = 4,
+ .val_bits = 32,
+ .max_register = TEGRA264_ADMAIF_LAST_REG,
+ .writeable_reg = tegra_admaif_wr_reg,
+ .readable_reg = tegra_admaif_rd_reg,
+ .volatile_reg = tegra_admaif_volatile_reg,
+ .reg_defaults = tegra264_admaif_reg_defaults,
+ .num_reg_defaults = TEGRA264_ADMAIF_CHANNEL_COUNT * 6 + 1,
+ .cache_type = REGCACHE_FLAT,
+};
+
+static int tegra_admaif_runtime_suspend(struct device *dev)
{
struct tegra_admaif *admaif = dev_get_drvdata(dev);
@@ -229,7 +280,7 @@ static int __maybe_unused tegra_admaif_runtime_suspend(struct device *dev)
return 0;
}
-static int __maybe_unused tegra_admaif_runtime_resume(struct device *dev)
+static int tegra_admaif_runtime_resume(struct device *dev)
{
struct tegra_admaif *admaif = dev_get_drvdata(dev);
@@ -262,6 +313,18 @@ static int tegra_admaif_set_pack_mode(struct regmap *map, unsigned int reg,
return 0;
}
+static int tegra_admaif_prepare(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+ return tegra_isomgr_adma_setbw(substream, dai, true);
+}
+
+static void tegra_admaif_shutdown(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+ tegra_isomgr_adma_setbw(substream, dai, false);
+}
+
static int tegra_admaif_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params,
struct snd_soc_dai *dai)
@@ -285,6 +348,11 @@ static int tegra_admaif_hw_params(struct snd_pcm_substream *substream,
cif_conf.client_bits = TEGRA_ACIF_BITS_16;
valid_bit = DATA_16BIT;
break;
+ case SNDRV_PCM_FORMAT_S24_LE:
+ cif_conf.audio_bits = TEGRA_ACIF_BITS_32;
+ cif_conf.client_bits = TEGRA_ACIF_BITS_24;
+ valid_bit = DATA_32BIT;
+ break;
case SNDRV_PCM_FORMAT_S32_LE:
cif_conf.audio_bits = TEGRA_ACIF_BITS_32;
cif_conf.client_bits = TEGRA_ACIF_BITS_32;
@@ -312,7 +380,10 @@ static int tegra_admaif_hw_params(struct snd_pcm_substream *substream,
tegra_admaif_set_pack_mode(admaif->regmap, reg, valid_bit);
- tegra_set_cif(admaif->regmap, reg, &cif_conf);
+ if (admaif->soc_data->max_stream_ch == TEGRA264_ADMAIF_MAX_CHANNEL)
+ tegra264_set_cif(admaif->regmap, reg, &cif_conf);
+ else
+ tegra_set_cif(admaif->regmap, reg, &cif_conf);
return 0;
}
@@ -549,66 +620,105 @@ static const struct snd_soc_dai_ops tegra_admaif_dai_ops = {
.probe = tegra_admaif_dai_probe,
.hw_params = tegra_admaif_hw_params,
.trigger = tegra_admaif_trigger,
+ .shutdown = tegra_admaif_shutdown,
+ .prepare = tegra_admaif_prepare,
};
-#define DAI(dai_name) \
+#define DAI(dai_name, channel) \
{ \
.name = dai_name, \
.playback = { \
.stream_name = dai_name " Playback", \
.channels_min = 1, \
- .channels_max = 16, \
+ .channels_max = channel, \
.rates = SNDRV_PCM_RATE_8000_192000, \
.formats = SNDRV_PCM_FMTBIT_S8 | \
SNDRV_PCM_FMTBIT_S16_LE | \
+ SNDRV_PCM_FMTBIT_S24_LE | \
SNDRV_PCM_FMTBIT_S32_LE, \
}, \
.capture = { \
.stream_name = dai_name " Capture", \
.channels_min = 1, \
- .channels_max = 16, \
+ .channels_max = channel, \
.rates = SNDRV_PCM_RATE_8000_192000, \
.formats = SNDRV_PCM_FMTBIT_S8 | \
SNDRV_PCM_FMTBIT_S16_LE | \
+ SNDRV_PCM_FMTBIT_S24_LE | \
SNDRV_PCM_FMTBIT_S32_LE, \
}, \
.ops = &tegra_admaif_dai_ops, \
}
static struct snd_soc_dai_driver tegra210_admaif_cmpnt_dais[] = {
- DAI("ADMAIF1"),
- DAI("ADMAIF2"),
- DAI("ADMAIF3"),
- DAI("ADMAIF4"),
- DAI("ADMAIF5"),
- DAI("ADMAIF6"),
- DAI("ADMAIF7"),
- DAI("ADMAIF8"),
- DAI("ADMAIF9"),
- DAI("ADMAIF10"),
+ DAI("ADMAIF1", TEGRA210_ADMAIF_MAX_CHANNEL),
+ DAI("ADMAIF2", TEGRA210_ADMAIF_MAX_CHANNEL),
+ DAI("ADMAIF3", TEGRA210_ADMAIF_MAX_CHANNEL),
+ DAI("ADMAIF4", TEGRA210_ADMAIF_MAX_CHANNEL),
+ DAI("ADMAIF5", TEGRA210_ADMAIF_MAX_CHANNEL),
+ DAI("ADMAIF6", TEGRA210_ADMAIF_MAX_CHANNEL),
+ DAI("ADMAIF7", TEGRA210_ADMAIF_MAX_CHANNEL),
+ DAI("ADMAIF8", TEGRA210_ADMAIF_MAX_CHANNEL),
+ DAI("ADMAIF9", TEGRA210_ADMAIF_MAX_CHANNEL),
+ DAI("ADMAIF10", TEGRA210_ADMAIF_MAX_CHANNEL),
};
static struct snd_soc_dai_driver tegra186_admaif_cmpnt_dais[] = {
- DAI("ADMAIF1"),
- DAI("ADMAIF2"),
- DAI("ADMAIF3"),
- DAI("ADMAIF4"),
- DAI("ADMAIF5"),
- DAI("ADMAIF6"),
- DAI("ADMAIF7"),
- DAI("ADMAIF8"),
- DAI("ADMAIF9"),
- DAI("ADMAIF10"),
- DAI("ADMAIF11"),
- DAI("ADMAIF12"),
- DAI("ADMAIF13"),
- DAI("ADMAIF14"),
- DAI("ADMAIF15"),
- DAI("ADMAIF16"),
- DAI("ADMAIF17"),
- DAI("ADMAIF18"),
- DAI("ADMAIF19"),
- DAI("ADMAIF20"),
+ DAI("ADMAIF1", TEGRA186_ADMAIF_MAX_CHANNEL),
+ DAI("ADMAIF2", TEGRA186_ADMAIF_MAX_CHANNEL),
+ DAI("ADMAIF3", TEGRA186_ADMAIF_MAX_CHANNEL),
+ DAI("ADMAIF4", TEGRA186_ADMAIF_MAX_CHANNEL),
+ DAI("ADMAIF5", TEGRA186_ADMAIF_MAX_CHANNEL),
+ DAI("ADMAIF6", TEGRA186_ADMAIF_MAX_CHANNEL),
+ DAI("ADMAIF7", TEGRA186_ADMAIF_MAX_CHANNEL),
+ DAI("ADMAIF8", TEGRA186_ADMAIF_MAX_CHANNEL),
+ DAI("ADMAIF9", TEGRA186_ADMAIF_MAX_CHANNEL),
+ DAI("ADMAIF10", TEGRA186_ADMAIF_MAX_CHANNEL),
+ DAI("ADMAIF11", TEGRA186_ADMAIF_MAX_CHANNEL),
+ DAI("ADMAIF12", TEGRA186_ADMAIF_MAX_CHANNEL),
+ DAI("ADMAIF13", TEGRA186_ADMAIF_MAX_CHANNEL),
+ DAI("ADMAIF14", TEGRA186_ADMAIF_MAX_CHANNEL),
+ DAI("ADMAIF15", TEGRA186_ADMAIF_MAX_CHANNEL),
+ DAI("ADMAIF16", TEGRA186_ADMAIF_MAX_CHANNEL),
+ DAI("ADMAIF17", TEGRA186_ADMAIF_MAX_CHANNEL),
+ DAI("ADMAIF18", TEGRA186_ADMAIF_MAX_CHANNEL),
+ DAI("ADMAIF19", TEGRA186_ADMAIF_MAX_CHANNEL),
+ DAI("ADMAIF20", TEGRA186_ADMAIF_MAX_CHANNEL),
+};
+
+static struct snd_soc_dai_driver tegra264_admaif_cmpnt_dais[] = {
+ DAI("ADMAIF1", TEGRA264_ADMAIF_MAX_CHANNEL),
+ DAI("ADMAIF2", TEGRA264_ADMAIF_MAX_CHANNEL),
+ DAI("ADMAIF3", TEGRA264_ADMAIF_MAX_CHANNEL),
+ DAI("ADMAIF4", TEGRA264_ADMAIF_MAX_CHANNEL),
+ DAI("ADMAIF5", TEGRA264_ADMAIF_MAX_CHANNEL),
+ DAI("ADMAIF6", TEGRA264_ADMAIF_MAX_CHANNEL),
+ DAI("ADMAIF7", TEGRA264_ADMAIF_MAX_CHANNEL),
+ DAI("ADMAIF8", TEGRA264_ADMAIF_MAX_CHANNEL),
+ DAI("ADMAIF9", TEGRA264_ADMAIF_MAX_CHANNEL),
+ DAI("ADMAIF10", TEGRA264_ADMAIF_MAX_CHANNEL),
+ DAI("ADMAIF11", TEGRA264_ADMAIF_MAX_CHANNEL),
+ DAI("ADMAIF12", TEGRA264_ADMAIF_MAX_CHANNEL),
+ DAI("ADMAIF13", TEGRA264_ADMAIF_MAX_CHANNEL),
+ DAI("ADMAIF14", TEGRA264_ADMAIF_MAX_CHANNEL),
+ DAI("ADMAIF15", TEGRA264_ADMAIF_MAX_CHANNEL),
+ DAI("ADMAIF16", TEGRA264_ADMAIF_MAX_CHANNEL),
+ DAI("ADMAIF17", TEGRA264_ADMAIF_MAX_CHANNEL),
+ DAI("ADMAIF18", TEGRA264_ADMAIF_MAX_CHANNEL),
+ DAI("ADMAIF19", TEGRA264_ADMAIF_MAX_CHANNEL),
+ DAI("ADMAIF20", TEGRA264_ADMAIF_MAX_CHANNEL),
+ DAI("ADMAIF21", TEGRA264_ADMAIF_MAX_CHANNEL),
+ DAI("ADMAIF22", TEGRA264_ADMAIF_MAX_CHANNEL),
+ DAI("ADMAIF23", TEGRA264_ADMAIF_MAX_CHANNEL),
+ DAI("ADMAIF24", TEGRA264_ADMAIF_MAX_CHANNEL),
+ DAI("ADMAIF25", TEGRA264_ADMAIF_MAX_CHANNEL),
+ DAI("ADMAIF26", TEGRA264_ADMAIF_MAX_CHANNEL),
+ DAI("ADMAIF27", TEGRA264_ADMAIF_MAX_CHANNEL),
+ DAI("ADMAIF28", TEGRA264_ADMAIF_MAX_CHANNEL),
+ DAI("ADMAIF29", TEGRA264_ADMAIF_MAX_CHANNEL),
+ DAI("ADMAIF30", TEGRA264_ADMAIF_MAX_CHANNEL),
+ DAI("ADMAIF31", TEGRA264_ADMAIF_MAX_CHANNEL),
+ DAI("ADMAIF32", TEGRA264_ADMAIF_MAX_CHANNEL),
};
static const char * const tegra_admaif_stereo_conv_text[] = {
@@ -688,6 +798,41 @@ static struct snd_kcontrol_new tegra186_admaif_controls[] = {
TEGRA_ADMAIF_CIF_CTRL(20),
};
+static struct snd_kcontrol_new tegra264_admaif_controls[] = {
+ TEGRA_ADMAIF_CIF_CTRL(1),
+ TEGRA_ADMAIF_CIF_CTRL(2),
+ TEGRA_ADMAIF_CIF_CTRL(3),
+ TEGRA_ADMAIF_CIF_CTRL(4),
+ TEGRA_ADMAIF_CIF_CTRL(5),
+ TEGRA_ADMAIF_CIF_CTRL(6),
+ TEGRA_ADMAIF_CIF_CTRL(7),
+ TEGRA_ADMAIF_CIF_CTRL(8),
+ TEGRA_ADMAIF_CIF_CTRL(9),
+ TEGRA_ADMAIF_CIF_CTRL(10),
+ TEGRA_ADMAIF_CIF_CTRL(11),
+ TEGRA_ADMAIF_CIF_CTRL(12),
+ TEGRA_ADMAIF_CIF_CTRL(13),
+ TEGRA_ADMAIF_CIF_CTRL(14),
+ TEGRA_ADMAIF_CIF_CTRL(15),
+ TEGRA_ADMAIF_CIF_CTRL(16),
+ TEGRA_ADMAIF_CIF_CTRL(17),
+ TEGRA_ADMAIF_CIF_CTRL(18),
+ TEGRA_ADMAIF_CIF_CTRL(19),
+ TEGRA_ADMAIF_CIF_CTRL(20),
+ TEGRA_ADMAIF_CIF_CTRL(21),
+ TEGRA_ADMAIF_CIF_CTRL(22),
+ TEGRA_ADMAIF_CIF_CTRL(23),
+ TEGRA_ADMAIF_CIF_CTRL(24),
+ TEGRA_ADMAIF_CIF_CTRL(25),
+ TEGRA_ADMAIF_CIF_CTRL(26),
+ TEGRA_ADMAIF_CIF_CTRL(27),
+ TEGRA_ADMAIF_CIF_CTRL(28),
+ TEGRA_ADMAIF_CIF_CTRL(29),
+ TEGRA_ADMAIF_CIF_CTRL(30),
+ TEGRA_ADMAIF_CIF_CTRL(31),
+ TEGRA_ADMAIF_CIF_CTRL(32),
+};
+
static const struct snd_soc_component_driver tegra210_admaif_cmpnt = {
.controls = tegra210_admaif_controls,
.num_controls = ARRAY_SIZE(tegra210_admaif_controls),
@@ -708,8 +853,19 @@ static const struct snd_soc_component_driver tegra186_admaif_cmpnt = {
.pointer = tegra_pcm_pointer,
};
+static const struct snd_soc_component_driver tegra264_admaif_cmpnt = {
+ .controls = tegra264_admaif_controls,
+ .num_controls = ARRAY_SIZE(tegra264_admaif_controls),
+ .pcm_construct = tegra_pcm_construct,
+ .open = tegra_pcm_open,
+ .close = tegra_pcm_close,
+ .hw_params = tegra_pcm_hw_params,
+ .pointer = tegra_pcm_pointer,
+};
+
static const struct tegra_admaif_soc_data soc_data_tegra210 = {
.num_ch = TEGRA210_ADMAIF_CHANNEL_COUNT,
+ .max_stream_ch = TEGRA210_ADMAIF_MAX_CHANNEL,
.cmpnt = &tegra210_admaif_cmpnt,
.dais = tegra210_admaif_cmpnt_dais,
.regmap_conf = &tegra210_admaif_regmap_config,
@@ -720,6 +876,7 @@ static const struct tegra_admaif_soc_data soc_data_tegra210 = {
static const struct tegra_admaif_soc_data soc_data_tegra186 = {
.num_ch = TEGRA186_ADMAIF_CHANNEL_COUNT,
+ .max_stream_ch = TEGRA186_ADMAIF_MAX_CHANNEL,
.cmpnt = &tegra186_admaif_cmpnt,
.dais = tegra186_admaif_cmpnt_dais,
.regmap_conf = &tegra186_admaif_regmap_config,
@@ -728,9 +885,21 @@ static const struct tegra_admaif_soc_data soc_data_tegra186 = {
.rx_base = TEGRA186_ADMAIF_RX_BASE,
};
+static const struct tegra_admaif_soc_data soc_data_tegra264 = {
+ .num_ch = TEGRA264_ADMAIF_CHANNEL_COUNT,
+ .max_stream_ch = TEGRA264_ADMAIF_MAX_CHANNEL,
+ .cmpnt = &tegra264_admaif_cmpnt,
+ .dais = tegra264_admaif_cmpnt_dais,
+ .regmap_conf = &tegra264_admaif_regmap_config,
+ .global_base = TEGRA264_ADMAIF_GLOBAL_BASE,
+ .tx_base = TEGRA264_ADMAIF_TX_BASE,
+ .rx_base = TEGRA264_ADMAIF_RX_BASE,
+};
+
static const struct of_device_id tegra_admaif_of_match[] = {
{ .compatible = "nvidia,tegra210-admaif", .data = &soc_data_tegra210 },
{ .compatible = "nvidia,tegra186-admaif", .data = &soc_data_tegra186 },
+ { .compatible = "nvidia,tegra264-admaif", .data = &soc_data_tegra264 },
{},
};
MODULE_DEVICE_TABLE(of, tegra_admaif_of_match);
@@ -793,6 +962,12 @@ static int tegra_admaif_probe(struct platform_device *pdev)
regcache_cache_only(admaif->regmap, true);
+ err = tegra_isomgr_adma_register(&pdev->dev);
+ if (err) {
+ dev_err(&pdev->dev, "Failed to add interconnect path\n");
+ return err;
+ }
+
regmap_update_bits(admaif->regmap, admaif->soc_data->global_base +
TEGRA_ADMAIF_GLOBAL_ENABLE, 1, 1);
@@ -844,23 +1019,23 @@ static int tegra_admaif_probe(struct platform_device *pdev)
static void tegra_admaif_remove(struct platform_device *pdev)
{
+ tegra_isomgr_adma_unregister(&pdev->dev);
pm_runtime_disable(&pdev->dev);
}
static const struct dev_pm_ops tegra_admaif_pm_ops = {
- SET_RUNTIME_PM_OPS(tegra_admaif_runtime_suspend,
- tegra_admaif_runtime_resume, NULL)
- SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
- pm_runtime_force_resume)
+ RUNTIME_PM_OPS(tegra_admaif_runtime_suspend,
+ tegra_admaif_runtime_resume, NULL)
+ SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, pm_runtime_force_resume)
};
static struct platform_driver tegra_admaif_driver = {
.probe = tegra_admaif_probe,
- .remove_new = tegra_admaif_remove,
+ .remove = tegra_admaif_remove,
.driver = {
.name = "tegra210-admaif",
.of_match_table = tegra_admaif_of_match,
- .pm = &tegra_admaif_pm_ops,
+ .pm = pm_ptr(&tegra_admaif_pm_ops),
},
};
module_platform_driver(tegra_admaif_driver);
diff --git a/sound/soc/tegra/tegra210_admaif.h b/sound/soc/tegra/tegra210_admaif.h
index 96686dc92081..304d45c76a9a 100644
--- a/sound/soc/tegra/tegra210_admaif.h
+++ b/sound/soc/tegra/tegra210_admaif.h
@@ -1,8 +1,8 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * tegra210_admaif.h - Tegra ADMAIF registers
+/* SPDX-License-Identifier: GPL-2.0-only
+ * SPDX-FileCopyrightText: Copyright (c) 2020-2025 NVIDIA CORPORATION & AFFILIATES.
+ * All rights reserved.
*
- * Copyright (c) 2020 NVIDIA CORPORATION. All rights reserved.
+ * tegra210_admaif.h - Tegra ADMAIF registers
*
*/
@@ -16,12 +16,21 @@
#define TEGRA210_ADMAIF_RX_BASE 0x0
#define TEGRA210_ADMAIF_TX_BASE 0x300
#define TEGRA210_ADMAIF_GLOBAL_BASE 0x700
+#define TEGRA210_ADMAIF_MAX_CHANNEL 16
/* Tegra186 specific */
#define TEGRA186_ADMAIF_LAST_REG 0xd5f
#define TEGRA186_ADMAIF_CHANNEL_COUNT 20
#define TEGRA186_ADMAIF_RX_BASE 0x0
#define TEGRA186_ADMAIF_TX_BASE 0x500
#define TEGRA186_ADMAIF_GLOBAL_BASE 0xd00
+#define TEGRA186_ADMAIF_MAX_CHANNEL 16
+/* Tegra264 specific */
+#define TEGRA264_ADMAIF_LAST_REG 0x205f
+#define TEGRA264_ADMAIF_CHANNEL_COUNT 32
+#define TEGRA264_ADMAIF_RX_BASE 0x0
+#define TEGRA264_ADMAIF_TX_BASE 0x1000
+#define TEGRA264_ADMAIF_GLOBAL_BASE 0x2000
+#define TEGRA264_ADMAIF_MAX_CHANNEL 32
/* Global registers */
#define TEGRA_ADMAIF_GLOBAL_ENABLE 0x0
#define TEGRA_ADMAIF_GLOBAL_CG_0 0x8
@@ -66,6 +75,7 @@
#define SW_RESET_MASK 1
#define SW_RESET 1
/* Default values - Tegra210 */
+#define TEGRA210_ADMAIF_CIF_REG_DEFAULT 0x00007700
#define TEGRA210_ADMAIF_RX1_FIFO_CTRL_REG_DEFAULT 0x00000300
#define TEGRA210_ADMAIF_RX2_FIFO_CTRL_REG_DEFAULT 0x00000304
#define TEGRA210_ADMAIF_RX3_FIFO_CTRL_REG_DEFAULT 0x00000208
@@ -87,6 +97,7 @@
#define TEGRA210_ADMAIF_TX9_FIFO_CTRL_REG_DEFAULT 0x0180021a
#define TEGRA210_ADMAIF_TX10_FIFO_CTRL_REG_DEFAULT 0x0180021d
/* Default values - Tegra186 */
+#define TEGRA186_ADMAIF_CIF_REG_DEFAULT 0x00007700
#define TEGRA186_ADMAIF_RX1_FIFO_CTRL_REG_DEFAULT 0x00000300
#define TEGRA186_ADMAIF_RX2_FIFO_CTRL_REG_DEFAULT 0x00000304
#define TEGRA186_ADMAIF_RX3_FIFO_CTRL_REG_DEFAULT 0x00000308
@@ -127,6 +138,72 @@
#define TEGRA186_ADMAIF_TX18_FIFO_CTRL_REG_DEFAULT 0x01800237
#define TEGRA186_ADMAIF_TX19_FIFO_CTRL_REG_DEFAULT 0x0180023a
#define TEGRA186_ADMAIF_TX20_FIFO_CTRL_REG_DEFAULT 0x0180023d
+/* Default values - Tegra264 */
+#define TEGRA264_ADMAIF_CIF_REG_DEFAULT 0x00003f00
+#define TEGRA264_ADMAIF_RX1_FIFO_CTRL_REG_DEFAULT 0x00000200
+#define TEGRA264_ADMAIF_RX2_FIFO_CTRL_REG_DEFAULT 0x00000203
+#define TEGRA264_ADMAIF_RX3_FIFO_CTRL_REG_DEFAULT 0x00000206
+#define TEGRA264_ADMAIF_RX4_FIFO_CTRL_REG_DEFAULT 0x00000209
+#define TEGRA264_ADMAIF_RX5_FIFO_CTRL_REG_DEFAULT 0x0000020c
+#define TEGRA264_ADMAIF_RX6_FIFO_CTRL_REG_DEFAULT 0x0000020f
+#define TEGRA264_ADMAIF_RX7_FIFO_CTRL_REG_DEFAULT 0x00000212
+#define TEGRA264_ADMAIF_RX8_FIFO_CTRL_REG_DEFAULT 0x00000215
+#define TEGRA264_ADMAIF_RX9_FIFO_CTRL_REG_DEFAULT 0x00000218
+#define TEGRA264_ADMAIF_RX10_FIFO_CTRL_REG_DEFAULT 0x0000021b
+#define TEGRA264_ADMAIF_RX11_FIFO_CTRL_REG_DEFAULT 0x0000021e
+#define TEGRA264_ADMAIF_RX12_FIFO_CTRL_REG_DEFAULT 0x00000221
+#define TEGRA264_ADMAIF_RX13_FIFO_CTRL_REG_DEFAULT 0x00000224
+#define TEGRA264_ADMAIF_RX14_FIFO_CTRL_REG_DEFAULT 0x00000227
+#define TEGRA264_ADMAIF_RX15_FIFO_CTRL_REG_DEFAULT 0x0000022a
+#define TEGRA264_ADMAIF_RX16_FIFO_CTRL_REG_DEFAULT 0x0000022d
+#define TEGRA264_ADMAIF_RX17_FIFO_CTRL_REG_DEFAULT 0x00000230
+#define TEGRA264_ADMAIF_RX18_FIFO_CTRL_REG_DEFAULT 0x00000233
+#define TEGRA264_ADMAIF_RX19_FIFO_CTRL_REG_DEFAULT 0x00000236
+#define TEGRA264_ADMAIF_RX20_FIFO_CTRL_REG_DEFAULT 0x00000239
+#define TEGRA264_ADMAIF_RX21_FIFO_CTRL_REG_DEFAULT 0x0000023c
+#define TEGRA264_ADMAIF_RX22_FIFO_CTRL_REG_DEFAULT 0x0000023f
+#define TEGRA264_ADMAIF_RX23_FIFO_CTRL_REG_DEFAULT 0x00000242
+#define TEGRA264_ADMAIF_RX24_FIFO_CTRL_REG_DEFAULT 0x00000245
+#define TEGRA264_ADMAIF_RX25_FIFO_CTRL_REG_DEFAULT 0x00000248
+#define TEGRA264_ADMAIF_RX26_FIFO_CTRL_REG_DEFAULT 0x0000024b
+#define TEGRA264_ADMAIF_RX27_FIFO_CTRL_REG_DEFAULT 0x0000024e
+#define TEGRA264_ADMAIF_RX28_FIFO_CTRL_REG_DEFAULT 0x00000251
+#define TEGRA264_ADMAIF_RX29_FIFO_CTRL_REG_DEFAULT 0x00000254
+#define TEGRA264_ADMAIF_RX30_FIFO_CTRL_REG_DEFAULT 0x00000257
+#define TEGRA264_ADMAIF_RX31_FIFO_CTRL_REG_DEFAULT 0x0000025a
+#define TEGRA264_ADMAIF_RX32_FIFO_CTRL_REG_DEFAULT 0x0000025d
+#define TEGRA264_ADMAIF_TX1_FIFO_CTRL_REG_DEFAULT 0x01800200
+#define TEGRA264_ADMAIF_TX2_FIFO_CTRL_REG_DEFAULT 0x01800203
+#define TEGRA264_ADMAIF_TX3_FIFO_CTRL_REG_DEFAULT 0x01800206
+#define TEGRA264_ADMAIF_TX4_FIFO_CTRL_REG_DEFAULT 0x01800209
+#define TEGRA264_ADMAIF_TX5_FIFO_CTRL_REG_DEFAULT 0x0180020c
+#define TEGRA264_ADMAIF_TX6_FIFO_CTRL_REG_DEFAULT 0x0180020f
+#define TEGRA264_ADMAIF_TX7_FIFO_CTRL_REG_DEFAULT 0x01800212
+#define TEGRA264_ADMAIF_TX8_FIFO_CTRL_REG_DEFAULT 0x01800215
+#define TEGRA264_ADMAIF_TX9_FIFO_CTRL_REG_DEFAULT 0x01800218
+#define TEGRA264_ADMAIF_TX10_FIFO_CTRL_REG_DEFAULT 0x0180021b
+#define TEGRA264_ADMAIF_TX11_FIFO_CTRL_REG_DEFAULT 0x0180021e
+#define TEGRA264_ADMAIF_TX12_FIFO_CTRL_REG_DEFAULT 0x01800221
+#define TEGRA264_ADMAIF_TX13_FIFO_CTRL_REG_DEFAULT 0x01800224
+#define TEGRA264_ADMAIF_TX14_FIFO_CTRL_REG_DEFAULT 0x01800227
+#define TEGRA264_ADMAIF_TX15_FIFO_CTRL_REG_DEFAULT 0x0180022a
+#define TEGRA264_ADMAIF_TX16_FIFO_CTRL_REG_DEFAULT 0x0180022d
+#define TEGRA264_ADMAIF_TX17_FIFO_CTRL_REG_DEFAULT 0x01800230
+#define TEGRA264_ADMAIF_TX18_FIFO_CTRL_REG_DEFAULT 0x01800233
+#define TEGRA264_ADMAIF_TX19_FIFO_CTRL_REG_DEFAULT 0x01800236
+#define TEGRA264_ADMAIF_TX20_FIFO_CTRL_REG_DEFAULT 0x01800239
+#define TEGRA264_ADMAIF_TX21_FIFO_CTRL_REG_DEFAULT 0x0180023c
+#define TEGRA264_ADMAIF_TX22_FIFO_CTRL_REG_DEFAULT 0x0180023f
+#define TEGRA264_ADMAIF_TX23_FIFO_CTRL_REG_DEFAULT 0x01800242
+#define TEGRA264_ADMAIF_TX24_FIFO_CTRL_REG_DEFAULT 0x01800245
+#define TEGRA264_ADMAIF_TX25_FIFO_CTRL_REG_DEFAULT 0x01800248
+#define TEGRA264_ADMAIF_TX26_FIFO_CTRL_REG_DEFAULT 0x0180024b
+#define TEGRA264_ADMAIF_TX27_FIFO_CTRL_REG_DEFAULT 0x0180024e
+#define TEGRA264_ADMAIF_TX28_FIFO_CTRL_REG_DEFAULT 0x01800251
+#define TEGRA264_ADMAIF_TX29_FIFO_CTRL_REG_DEFAULT 0x01800254
+#define TEGRA264_ADMAIF_TX30_FIFO_CTRL_REG_DEFAULT 0x01800257
+#define TEGRA264_ADMAIF_TX31_FIFO_CTRL_REG_DEFAULT 0x0180025a
+#define TEGRA264_ADMAIF_TX32_FIFO_CTRL_REG_DEFAULT 0x0180025d
enum {
DATA_8BIT,
@@ -148,6 +225,7 @@ struct tegra_admaif_soc_data {
unsigned int tx_base;
unsigned int rx_base;
unsigned int num_ch;
+ unsigned int max_stream_ch;
};
struct tegra_admaif {
@@ -157,6 +235,7 @@ struct tegra_admaif {
unsigned int *mono_to_stereo[ADMAIF_PATHS];
unsigned int *stereo_to_mono[ADMAIF_PATHS];
struct regmap *regmap;
+ struct tegra_adma_isomgr *adma_isomgr;
};
#endif
diff --git a/sound/soc/tegra/tegra210_adx.c b/sound/soc/tegra/tegra210_adx.c
index d2530443a221..ad7cd8655047 100644
--- a/sound/soc/tegra/tegra210_adx.c
+++ b/sound/soc/tegra/tegra210_adx.c
@@ -1,14 +1,15 @@
// SPDX-License-Identifier: GPL-2.0-only
+// SPDX-FileCopyrightText: Copyright (c) 2021-2025 NVIDIA CORPORATION & AFFILIATES.
+// All rights reserved.
//
// tegra210_adx.c - Tegra210 ADX driver
-//
-// Copyright (c) 2021-2023 NVIDIA CORPORATION. All rights reserved.
#include <linux/clk.h>
#include <linux/device.h>
#include <linux/io.h>
#include <linux/mod_devicetable.h>
#include <linux/module.h>
+#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/regmap.h>
@@ -32,21 +33,37 @@ static const struct reg_default tegra210_adx_reg_defaults[] = {
{ TEGRA210_ADX_CFG_RAM_CTRL, 0x00004000},
};
+static const struct reg_default tegra264_adx_reg_defaults[] = {
+ { TEGRA210_ADX_RX_INT_MASK, 0x00000001},
+ { TEGRA210_ADX_RX_CIF_CTRL, 0x00003800},
+ { TEGRA210_ADX_TX_INT_MASK, 0x0000000f },
+ { TEGRA210_ADX_TX1_CIF_CTRL, 0x00003800},
+ { TEGRA210_ADX_TX2_CIF_CTRL, 0x00003800},
+ { TEGRA210_ADX_TX3_CIF_CTRL, 0x00003800},
+ { TEGRA210_ADX_TX4_CIF_CTRL, 0x00003800},
+ { TEGRA210_ADX_CG, 0x1},
+ { TEGRA264_ADX_CFG_RAM_CTRL, 0x00004000},
+};
+
static void tegra210_adx_write_map_ram(struct tegra210_adx *adx)
{
int i;
- regmap_write(adx->regmap, TEGRA210_ADX_CFG_RAM_CTRL,
+ regmap_write(adx->regmap, TEGRA210_ADX_CFG_RAM_CTRL +
+ adx->soc_data->cya_offset,
TEGRA210_ADX_CFG_RAM_CTRL_SEQ_ACCESS_EN |
TEGRA210_ADX_CFG_RAM_CTRL_ADDR_INIT_EN |
TEGRA210_ADX_CFG_RAM_CTRL_RW_WRITE);
- for (i = 0; i < TEGRA210_ADX_RAM_DEPTH; i++)
- regmap_write(adx->regmap, TEGRA210_ADX_CFG_RAM_DATA,
+ for (i = 0; i < adx->soc_data->ram_depth; i++)
+ regmap_write(adx->regmap, TEGRA210_ADX_CFG_RAM_DATA +
+ adx->soc_data->cya_offset,
adx->map[i]);
- regmap_write(adx->regmap, TEGRA210_ADX_IN_BYTE_EN0, adx->byte_mask[0]);
- regmap_write(adx->regmap, TEGRA210_ADX_IN_BYTE_EN1, adx->byte_mask[1]);
+ for (i = 0; i < adx->soc_data->byte_mask_size; i++)
+ regmap_write(adx->regmap,
+ TEGRA210_ADX_IN_BYTE_EN0 + (i * TEGRA210_ADX_AUDIOCIF_CH_STRIDE),
+ adx->byte_mask[i]);
}
static int tegra210_adx_startup(struct snd_pcm_substream *substream,
@@ -57,8 +74,8 @@ static int tegra210_adx_startup(struct snd_pcm_substream *substream,
int err;
/* Ensure if ADX status is disabled */
- err = regmap_read_poll_timeout_atomic(adx->regmap, TEGRA210_ADX_STATUS,
- val, !(val & 0x1), 10, 10000);
+ err = regmap_read_poll_timeout(adx->regmap, TEGRA210_ADX_STATUS,
+ val, !(val & 0x1), 10, 10000);
if (err < 0) {
dev_err(dai->dev, "failed to stop ADX, err = %d\n", err);
return err;
@@ -84,7 +101,7 @@ static int tegra210_adx_startup(struct snd_pcm_substream *substream,
return 0;
}
-static int __maybe_unused tegra210_adx_runtime_suspend(struct device *dev)
+static int tegra210_adx_runtime_suspend(struct device *dev)
{
struct tegra210_adx *adx = dev_get_drvdata(dev);
@@ -94,7 +111,7 @@ static int __maybe_unused tegra210_adx_runtime_suspend(struct device *dev)
return 0;
}
-static int __maybe_unused tegra210_adx_runtime_resume(struct device *dev)
+static int tegra210_adx_runtime_resume(struct device *dev)
{
struct tegra210_adx *adx = dev_get_drvdata(dev);
@@ -117,7 +134,7 @@ static int tegra210_adx_set_audio_cif(struct snd_soc_dai *dai,
memset(&cif_conf, 0, sizeof(struct tegra_cif_conf));
- if (channels < 1 || channels > 16)
+ if (channels < 1 || channels > adx->soc_data->max_ch)
return -EINVAL;
switch (format) {
@@ -127,6 +144,7 @@ static int tegra210_adx_set_audio_cif(struct snd_soc_dai *dai,
case SNDRV_PCM_FORMAT_S16_LE:
audio_bits = TEGRA_ACIF_BITS_16;
break;
+ case SNDRV_PCM_FORMAT_S24_LE:
case SNDRV_PCM_FORMAT_S32_LE:
audio_bits = TEGRA_ACIF_BITS_32;
break;
@@ -139,7 +157,10 @@ static int tegra210_adx_set_audio_cif(struct snd_soc_dai *dai,
cif_conf.audio_bits = audio_bits;
cif_conf.client_bits = audio_bits;
- tegra_set_cif(adx->regmap, reg, &cif_conf);
+ if (adx->soc_data->max_ch == 32)
+ tegra264_set_cif(adx->regmap, reg, &cif_conf);
+ else
+ tegra_set_cif(adx->regmap, reg, &cif_conf);
return 0;
}
@@ -168,7 +189,7 @@ static int tegra210_adx_get_byte_map(struct snd_kcontrol *kcontrol,
struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
struct tegra210_adx *adx = snd_soc_component_get_drvdata(cmpnt);
struct soc_mixer_control *mc;
- unsigned char *bytes_map = (unsigned char *)&adx->map;
+ unsigned char *bytes_map = (unsigned char *)adx->map;
int enabled;
mc = (struct soc_mixer_control *)kcontrol->private_value;
@@ -197,7 +218,7 @@ static int tegra210_adx_put_byte_map(struct snd_kcontrol *kcontrol,
{
struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
struct tegra210_adx *adx = snd_soc_component_get_drvdata(cmpnt);
- unsigned char *bytes_map = (unsigned char *)&adx->map;
+ unsigned char *bytes_map = (unsigned char *)adx->map;
int value = ucontrol->value.integer.value[0];
struct soc_mixer_control *mc =
(struct soc_mixer_control *)kcontrol->private_value;
@@ -237,6 +258,7 @@ static const struct snd_soc_dai_ops tegra210_adx_out_dai_ops = {
.rates = SNDRV_PCM_RATE_8000_192000, \
.formats = SNDRV_PCM_FMTBIT_S8 | \
SNDRV_PCM_FMTBIT_S16_LE | \
+ SNDRV_PCM_FMTBIT_S24_LE | \
SNDRV_PCM_FMTBIT_S32_LE, \
}, \
.capture = { \
@@ -246,6 +268,7 @@ static const struct snd_soc_dai_ops tegra210_adx_out_dai_ops = {
.rates = SNDRV_PCM_RATE_8000_192000, \
.formats = SNDRV_PCM_FMTBIT_S8 | \
SNDRV_PCM_FMTBIT_S16_LE | \
+ SNDRV_PCM_FMTBIT_S24_LE | \
SNDRV_PCM_FMTBIT_S32_LE, \
}, \
.ops = &tegra210_adx_in_dai_ops, \
@@ -261,6 +284,7 @@ static const struct snd_soc_dai_ops tegra210_adx_out_dai_ops = {
.rates = SNDRV_PCM_RATE_8000_192000, \
.formats = SNDRV_PCM_FMTBIT_S8 | \
SNDRV_PCM_FMTBIT_S16_LE | \
+ SNDRV_PCM_FMTBIT_S24_LE | \
SNDRV_PCM_FMTBIT_S32_LE, \
}, \
.capture = { \
@@ -270,6 +294,7 @@ static const struct snd_soc_dai_ops tegra210_adx_out_dai_ops = {
.rates = SNDRV_PCM_RATE_8000_192000, \
.formats = SNDRV_PCM_FMTBIT_S8 | \
SNDRV_PCM_FMTBIT_S16_LE | \
+ SNDRV_PCM_FMTBIT_S24_LE | \
SNDRV_PCM_FMTBIT_S32_LE, \
}, \
.ops = &tegra210_adx_out_dai_ops, \
@@ -397,7 +422,90 @@ static struct snd_kcontrol_new tegra210_adx_controls[] = {
TEGRA210_ADX_BYTE_MAP_CTRL(63),
};
+static struct snd_kcontrol_new tegra264_adx_controls[] = {
+ TEGRA210_ADX_BYTE_MAP_CTRL(64),
+ TEGRA210_ADX_BYTE_MAP_CTRL(65),
+ TEGRA210_ADX_BYTE_MAP_CTRL(66),
+ TEGRA210_ADX_BYTE_MAP_CTRL(67),
+ TEGRA210_ADX_BYTE_MAP_CTRL(68),
+ TEGRA210_ADX_BYTE_MAP_CTRL(69),
+ TEGRA210_ADX_BYTE_MAP_CTRL(70),
+ TEGRA210_ADX_BYTE_MAP_CTRL(71),
+ TEGRA210_ADX_BYTE_MAP_CTRL(72),
+ TEGRA210_ADX_BYTE_MAP_CTRL(73),
+ TEGRA210_ADX_BYTE_MAP_CTRL(74),
+ TEGRA210_ADX_BYTE_MAP_CTRL(75),
+ TEGRA210_ADX_BYTE_MAP_CTRL(76),
+ TEGRA210_ADX_BYTE_MAP_CTRL(77),
+ TEGRA210_ADX_BYTE_MAP_CTRL(78),
+ TEGRA210_ADX_BYTE_MAP_CTRL(79),
+ TEGRA210_ADX_BYTE_MAP_CTRL(80),
+ TEGRA210_ADX_BYTE_MAP_CTRL(81),
+ TEGRA210_ADX_BYTE_MAP_CTRL(82),
+ TEGRA210_ADX_BYTE_MAP_CTRL(83),
+ TEGRA210_ADX_BYTE_MAP_CTRL(84),
+ TEGRA210_ADX_BYTE_MAP_CTRL(85),
+ TEGRA210_ADX_BYTE_MAP_CTRL(86),
+ TEGRA210_ADX_BYTE_MAP_CTRL(87),
+ TEGRA210_ADX_BYTE_MAP_CTRL(88),
+ TEGRA210_ADX_BYTE_MAP_CTRL(89),
+ TEGRA210_ADX_BYTE_MAP_CTRL(90),
+ TEGRA210_ADX_BYTE_MAP_CTRL(91),
+ TEGRA210_ADX_BYTE_MAP_CTRL(92),
+ TEGRA210_ADX_BYTE_MAP_CTRL(93),
+ TEGRA210_ADX_BYTE_MAP_CTRL(94),
+ TEGRA210_ADX_BYTE_MAP_CTRL(95),
+ TEGRA210_ADX_BYTE_MAP_CTRL(96),
+ TEGRA210_ADX_BYTE_MAP_CTRL(97),
+ TEGRA210_ADX_BYTE_MAP_CTRL(98),
+ TEGRA210_ADX_BYTE_MAP_CTRL(99),
+ TEGRA210_ADX_BYTE_MAP_CTRL(100),
+ TEGRA210_ADX_BYTE_MAP_CTRL(101),
+ TEGRA210_ADX_BYTE_MAP_CTRL(102),
+ TEGRA210_ADX_BYTE_MAP_CTRL(103),
+ TEGRA210_ADX_BYTE_MAP_CTRL(104),
+ TEGRA210_ADX_BYTE_MAP_CTRL(105),
+ TEGRA210_ADX_BYTE_MAP_CTRL(106),
+ TEGRA210_ADX_BYTE_MAP_CTRL(107),
+ TEGRA210_ADX_BYTE_MAP_CTRL(108),
+ TEGRA210_ADX_BYTE_MAP_CTRL(109),
+ TEGRA210_ADX_BYTE_MAP_CTRL(110),
+ TEGRA210_ADX_BYTE_MAP_CTRL(111),
+ TEGRA210_ADX_BYTE_MAP_CTRL(112),
+ TEGRA210_ADX_BYTE_MAP_CTRL(113),
+ TEGRA210_ADX_BYTE_MAP_CTRL(114),
+ TEGRA210_ADX_BYTE_MAP_CTRL(115),
+ TEGRA210_ADX_BYTE_MAP_CTRL(116),
+ TEGRA210_ADX_BYTE_MAP_CTRL(117),
+ TEGRA210_ADX_BYTE_MAP_CTRL(118),
+ TEGRA210_ADX_BYTE_MAP_CTRL(119),
+ TEGRA210_ADX_BYTE_MAP_CTRL(120),
+ TEGRA210_ADX_BYTE_MAP_CTRL(121),
+ TEGRA210_ADX_BYTE_MAP_CTRL(122),
+ TEGRA210_ADX_BYTE_MAP_CTRL(123),
+ TEGRA210_ADX_BYTE_MAP_CTRL(124),
+ TEGRA210_ADX_BYTE_MAP_CTRL(125),
+ TEGRA210_ADX_BYTE_MAP_CTRL(126),
+ TEGRA210_ADX_BYTE_MAP_CTRL(127),
+};
+
+static int tegra210_adx_component_probe(struct snd_soc_component *component)
+{
+ struct tegra210_adx *adx = snd_soc_component_get_drvdata(component);
+ int err = 0;
+
+ if (adx->soc_data->num_controls) {
+ err = snd_soc_add_component_controls(component, adx->soc_data->controls,
+ adx->soc_data->num_controls);
+ if (err)
+ dev_err(component->dev, "can't add ADX controls, err: %d\n", err);
+ }
+
+ return err;
+}
+
static const struct snd_soc_component_driver tegra210_adx_cmpnt = {
+ .probe = tegra210_adx_component_probe,
.dapm_widgets = tegra210_adx_widgets,
.num_dapm_widgets = ARRAY_SIZE(tegra210_adx_widgets),
.dapm_routes = tegra210_adx_routes,
@@ -455,6 +563,58 @@ static bool tegra210_adx_volatile_reg(struct device *dev,
return false;
}
+static bool tegra264_adx_wr_reg(struct device *dev,
+ unsigned int reg)
+{
+ switch (reg) {
+ case TEGRA210_ADX_TX_INT_MASK ... TEGRA210_ADX_TX4_CIF_CTRL:
+ case TEGRA210_ADX_RX_INT_MASK ... TEGRA210_ADX_RX_CIF_CTRL:
+ case TEGRA210_ADX_ENABLE ... TEGRA210_ADX_CG:
+ case TEGRA210_ADX_CTRL ... TEGRA264_ADX_CYA:
+ case TEGRA264_ADX_CFG_RAM_CTRL ... TEGRA264_ADX_CFG_RAM_DATA:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static bool tegra264_adx_rd_reg(struct device *dev,
+ unsigned int reg)
+{
+ switch (reg) {
+ case TEGRA210_ADX_RX_STATUS ... TEGRA210_ADX_RX_CIF_CTRL:
+ case TEGRA210_ADX_TX_STATUS ... TEGRA210_ADX_TX4_CIF_CTRL:
+ case TEGRA210_ADX_ENABLE ... TEGRA210_ADX_INT_STATUS:
+ case TEGRA210_ADX_CTRL ... TEGRA264_ADX_CFG_RAM_DATA:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static bool tegra264_adx_volatile_reg(struct device *dev,
+ unsigned int reg)
+{
+ switch (reg) {
+ case TEGRA210_ADX_RX_STATUS:
+ case TEGRA210_ADX_RX_INT_STATUS:
+ case TEGRA210_ADX_RX_INT_SET:
+ case TEGRA210_ADX_TX_STATUS:
+ case TEGRA210_ADX_TX_INT_STATUS:
+ case TEGRA210_ADX_TX_INT_SET:
+ case TEGRA210_ADX_SOFT_RESET:
+ case TEGRA210_ADX_STATUS:
+ case TEGRA210_ADX_INT_STATUS:
+ case TEGRA264_ADX_CFG_RAM_CTRL:
+ case TEGRA264_ADX_CFG_RAM_DATA:
+ return true;
+ default:
+ break;
+ }
+
+ return false;
+}
+
static const struct regmap_config tegra210_adx_regmap_config = {
.reg_bits = 32,
.reg_stride = 4,
@@ -468,8 +628,40 @@ static const struct regmap_config tegra210_adx_regmap_config = {
.cache_type = REGCACHE_FLAT,
};
+static const struct regmap_config tegra264_adx_regmap_config = {
+ .reg_bits = 32,
+ .reg_stride = 4,
+ .val_bits = 32,
+ .max_register = TEGRA264_ADX_CFG_RAM_DATA,
+ .writeable_reg = tegra264_adx_wr_reg,
+ .readable_reg = tegra264_adx_rd_reg,
+ .volatile_reg = tegra264_adx_volatile_reg,
+ .reg_defaults = tegra264_adx_reg_defaults,
+ .num_reg_defaults = ARRAY_SIZE(tegra264_adx_reg_defaults),
+ .cache_type = REGCACHE_FLAT,
+};
+
+static const struct tegra210_adx_soc_data soc_data_tegra210 = {
+ .regmap_conf = &tegra210_adx_regmap_config,
+ .max_ch = TEGRA210_ADX_MAX_CHANNEL,
+ .ram_depth = TEGRA210_ADX_RAM_DEPTH,
+ .byte_mask_size = TEGRA210_ADX_BYTE_MASK_COUNT,
+ .cya_offset = TEGRA210_ADX_CYA_OFFSET,
+};
+
+static const struct tegra210_adx_soc_data soc_data_tegra264 = {
+ .regmap_conf = &tegra264_adx_regmap_config,
+ .max_ch = TEGRA264_ADX_MAX_CHANNEL,
+ .ram_depth = TEGRA264_ADX_RAM_DEPTH,
+ .byte_mask_size = TEGRA264_ADX_BYTE_MASK_COUNT,
+ .cya_offset = TEGRA264_ADX_CYA_OFFSET,
+ .controls = tegra264_adx_controls,
+ .num_controls = ARRAY_SIZE(tegra264_adx_controls),
+};
+
static const struct of_device_id tegra210_adx_of_match[] = {
- { .compatible = "nvidia,tegra210-adx" },
+ { .compatible = "nvidia,tegra210-adx", .data = &soc_data_tegra210 },
+ { .compatible = "nvidia,tegra264-adx", .data = &soc_data_tegra264 },
{},
};
MODULE_DEVICE_TABLE(of, tegra210_adx_of_match);
@@ -478,6 +670,8 @@ static int tegra210_adx_platform_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct tegra210_adx *adx;
+ const struct of_device_id *match;
+ struct tegra210_adx_soc_data *soc_data;
void __iomem *regs;
int err;
@@ -485,6 +679,10 @@ static int tegra210_adx_platform_probe(struct platform_device *pdev)
if (!adx)
return -ENOMEM;
+ match = of_match_device(tegra210_adx_of_match, dev);
+ soc_data = (struct tegra210_adx_soc_data *)match->data;
+ adx->soc_data = soc_data;
+
dev_set_drvdata(dev, adx);
regs = devm_platform_ioremap_resource(pdev, 0);
@@ -492,7 +690,7 @@ static int tegra210_adx_platform_probe(struct platform_device *pdev)
return PTR_ERR(regs);
adx->regmap = devm_regmap_init_mmio(dev, regs,
- &tegra210_adx_regmap_config);
+ soc_data->regmap_conf);
if (IS_ERR(adx->regmap)) {
dev_err(dev, "regmap init failed\n");
return PTR_ERR(adx->regmap);
@@ -500,6 +698,20 @@ static int tegra210_adx_platform_probe(struct platform_device *pdev)
regcache_cache_only(adx->regmap, true);
+ adx->map = devm_kzalloc(dev, soc_data->ram_depth * sizeof(*adx->map),
+ GFP_KERNEL);
+ if (!adx->map)
+ return -ENOMEM;
+
+ adx->byte_mask = devm_kzalloc(dev,
+ soc_data->byte_mask_size * sizeof(*adx->byte_mask),
+ GFP_KERNEL);
+ if (!adx->byte_mask)
+ return -ENOMEM;
+
+ tegra210_adx_dais[TEGRA_ADX_IN_DAI_ID].playback.channels_max =
+ adx->soc_data->max_ch;
+
err = devm_snd_soc_register_component(dev, &tegra210_adx_cmpnt,
tegra210_adx_dais,
ARRAY_SIZE(tegra210_adx_dais));
@@ -519,20 +731,19 @@ static void tegra210_adx_platform_remove(struct platform_device *pdev)
}
static const struct dev_pm_ops tegra210_adx_pm_ops = {
- SET_RUNTIME_PM_OPS(tegra210_adx_runtime_suspend,
- tegra210_adx_runtime_resume, NULL)
- SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
- pm_runtime_force_resume)
+ RUNTIME_PM_OPS(tegra210_adx_runtime_suspend,
+ tegra210_adx_runtime_resume, NULL)
+ SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, pm_runtime_force_resume)
};
static struct platform_driver tegra210_adx_driver = {
.driver = {
.name = "tegra210-adx",
.of_match_table = tegra210_adx_of_match,
- .pm = &tegra210_adx_pm_ops,
+ .pm = pm_ptr(&tegra210_adx_pm_ops),
},
.probe = tegra210_adx_platform_probe,
- .remove_new = tegra210_adx_platform_remove,
+ .remove = tegra210_adx_platform_remove,
};
module_platform_driver(tegra210_adx_driver);
diff --git a/sound/soc/tegra/tegra210_adx.h b/sound/soc/tegra/tegra210_adx.h
index d7dcb6497978..176a4e40de0a 100644
--- a/sound/soc/tegra/tegra210_adx.h
+++ b/sound/soc/tegra/tegra210_adx.h
@@ -1,8 +1,7 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * tegra210_adx.h - Definitions for Tegra210 ADX driver
+/* SPDX-License-Identifier: GPL-2.0-only
+ * SPDX-FileCopyrightText: Copyright (c) 2021-2025 NVIDIA CORPORATION. All rights reserved.
*
- * Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved.
+ * tegra210_adx.h - Definitions for Tegra210 ADX driver
*
*/
@@ -36,6 +35,10 @@
#define TEGRA210_ADX_CFG_RAM_CTRL 0xb8
#define TEGRA210_ADX_CFG_RAM_DATA 0xbc
+#define TEGRA264_ADX_CYA 0xb8
+#define TEGRA264_ADX_CFG_RAM_CTRL 0xc0
+#define TEGRA264_ADX_CFG_RAM_DATA 0xc4
+
/* Fields in TEGRA210_ADX_ENABLE */
#define TEGRA210_ADX_ENABLE_SHIFT 0
@@ -62,11 +65,32 @@
#define TEGRA210_ADX_MAP_STREAM_NUMBER_SHIFT 6
#define TEGRA210_ADX_MAP_WORD_NUMBER_SHIFT 2
#define TEGRA210_ADX_MAP_BYTE_NUMBER_SHIFT 0
+#define TEGRA210_ADX_BYTE_MASK_COUNT 2
+#define TEGRA210_ADX_MAX_CHANNEL 16
+#define TEGRA210_ADX_CYA_OFFSET 0
+
+#define TEGRA264_ADX_RAM_DEPTH 32
+#define TEGRA264_ADX_BYTE_MASK_COUNT 4
+#define TEGRA264_ADX_MAX_CHANNEL 32
+#define TEGRA264_ADX_CYA_OFFSET 8
+
+#define TEGRA_ADX_IN_DAI_ID 4
+
+struct tegra210_adx_soc_data {
+ const struct regmap_config *regmap_conf;
+ const struct snd_kcontrol_new *controls;
+ unsigned int num_controls;
+ unsigned int max_ch;
+ unsigned int ram_depth;
+ unsigned int byte_mask_size;
+ unsigned int cya_offset;
+};
struct tegra210_adx {
struct regmap *regmap;
- unsigned int map[TEGRA210_ADX_RAM_DEPTH];
- unsigned int byte_mask[2];
+ unsigned int *map;
+ unsigned int *byte_mask;
+ const struct tegra210_adx_soc_data *soc_data;
};
#endif
diff --git a/sound/soc/tegra/tegra210_ahub.c b/sound/soc/tegra/tegra210_ahub.c
index 3f114a2adfce..2376cc76e684 100644
--- a/sound/soc/tegra/tegra210_ahub.c
+++ b/sound/soc/tegra/tegra210_ahub.c
@@ -2,7 +2,7 @@
//
// tegra210_ahub.c - Tegra210 AHUB driver
//
-// Copyright (c) 2020-2022, NVIDIA CORPORATION. All rights reserved.
+// Copyright (c) 2020-2025, NVIDIA CORPORATION. All rights reserved.
#include <linux/clk.h>
#include <linux/device.h>
@@ -29,7 +29,7 @@ static int tegra_ahub_get_value_enum(struct snd_kcontrol *kctl,
for (i = 0; i < ahub->soc_data->reg_count; i++) {
unsigned int reg_val;
- reg = e->reg + (TEGRA210_XBAR_PART1_RX * i);
+ reg = e->reg + (ahub->soc_data->xbar_part_size * i);
reg_val = snd_soc_component_read(cmpnt, reg);
reg_val &= ahub->soc_data->mask[i];
@@ -80,7 +80,7 @@ static int tegra_ahub_put_value_enum(struct snd_kcontrol *kctl,
* different part of the MUX register.
*/
for (i = 0; i < ahub->soc_data->reg_count; i++) {
- update[i].reg = e->reg + (TEGRA210_XBAR_PART1_RX * i);
+ update[i].reg = e->reg + (ahub->soc_data->xbar_part_size * i);
update[i].val = (i == reg_idx) ? reg_val : 0;
update[i].mask = ahub->soc_data->mask[i];
update[i].kcontrol = kctl;
@@ -304,6 +304,164 @@ static struct snd_soc_dai_driver tegra186_ahub_dais[] = {
DAI(OPE1 TX),
};
+static struct snd_soc_dai_driver tegra264_ahub_dais[] = {
+ DAI(ADMAIF1),
+ DAI(ADMAIF2),
+ DAI(ADMAIF3),
+ DAI(ADMAIF4),
+ DAI(ADMAIF5),
+ DAI(ADMAIF6),
+ DAI(ADMAIF7),
+ DAI(ADMAIF8),
+ DAI(ADMAIF9),
+ DAI(ADMAIF10),
+ DAI(ADMAIF11),
+ DAI(ADMAIF12),
+ DAI(ADMAIF13),
+ DAI(ADMAIF14),
+ DAI(ADMAIF15),
+ DAI(ADMAIF16),
+ DAI(ADMAIF17),
+ DAI(ADMAIF18),
+ DAI(ADMAIF19),
+ DAI(ADMAIF20),
+ DAI(ADMAIF21),
+ DAI(ADMAIF22),
+ DAI(ADMAIF23),
+ DAI(ADMAIF24),
+ DAI(ADMAIF25),
+ DAI(ADMAIF26),
+ DAI(ADMAIF27),
+ DAI(ADMAIF28),
+ DAI(ADMAIF29),
+ DAI(ADMAIF30),
+ DAI(ADMAIF31),
+ DAI(ADMAIF32),
+ /* XBAR <-> I2S <-> Codec */
+ DAI(I2S1),
+ DAI(I2S2),
+ DAI(I2S3),
+ DAI(I2S4),
+ DAI(I2S5),
+ DAI(I2S6),
+ DAI(I2S7),
+ DAI(I2S8),
+ /* XBAR <-> DMIC <-> Codec */
+ DAI(DMIC1),
+ DAI(DMIC2),
+ /* XBAR <-> DSPK <-> Codec */
+ DAI(DSPK1),
+ /* XBAR -> SFC -> XBAR */
+ DAI(SFC1 RX),
+ DAI(SFC1 TX),
+ DAI(SFC2 RX),
+ DAI(SFC2 TX),
+ DAI(SFC3 RX),
+ DAI(SFC3 TX),
+ DAI(SFC4 RX),
+ DAI(SFC4 TX),
+ /* XBAR -> MVC -> XBAR */
+ DAI(MVC1 RX),
+ DAI(MVC1 TX),
+ DAI(MVC2 RX),
+ DAI(MVC2 TX),
+ /* XBAR -> AMX(4:1) -> XBAR */
+ DAI(AMX1 RX1),
+ DAI(AMX1 RX2),
+ DAI(AMX1 RX3),
+ DAI(AMX1 RX4),
+ DAI(AMX1),
+ DAI(AMX2 RX1),
+ DAI(AMX2 RX2),
+ DAI(AMX2 RX3),
+ DAI(AMX2 RX4),
+ DAI(AMX2),
+ DAI(AMX3 RX1),
+ DAI(AMX3 RX2),
+ DAI(AMX3 RX3),
+ DAI(AMX3 RX4),
+ DAI(AMX3),
+ DAI(AMX4 RX1),
+ DAI(AMX4 RX2),
+ DAI(AMX4 RX3),
+ DAI(AMX4 RX4),
+ DAI(AMX4),
+ DAI(AMX5 RX1),
+ DAI(AMX5 RX2),
+ DAI(AMX5 RX3),
+ DAI(AMX5 RX4),
+ DAI(AMX5),
+ DAI(AMX6 RX1),
+ DAI(AMX6 RX2),
+ DAI(AMX6 RX3),
+ DAI(AMX6 RX4),
+ DAI(AMX6),
+ /* XBAR -> ADX(1:4) -> XBAR */
+ DAI(ADX1),
+ DAI(ADX1 TX1),
+ DAI(ADX1 TX2),
+ DAI(ADX1 TX3),
+ DAI(ADX1 TX4),
+ DAI(ADX2),
+ DAI(ADX2 TX1),
+ DAI(ADX2 TX2),
+ DAI(ADX2 TX3),
+ DAI(ADX2 TX4),
+ DAI(ADX3),
+ DAI(ADX3 TX1),
+ DAI(ADX3 TX2),
+ DAI(ADX3 TX3),
+ DAI(ADX3 TX4),
+ DAI(ADX4),
+ DAI(ADX4 TX1),
+ DAI(ADX4 TX2),
+ DAI(ADX4 TX3),
+ DAI(ADX4 TX4),
+ DAI(ADX5),
+ DAI(ADX5 TX1),
+ DAI(ADX5 TX2),
+ DAI(ADX5 TX3),
+ DAI(ADX5 TX4),
+ DAI(ADX6),
+ DAI(ADX6 TX1),
+ DAI(ADX6 TX2),
+ DAI(ADX6 TX3),
+ DAI(ADX6 TX4),
+ /* XBAR -> MIXER1(10:5) -> XBAR */
+ DAI(MIXER1 RX1),
+ DAI(MIXER1 RX2),
+ DAI(MIXER1 RX3),
+ DAI(MIXER1 RX4),
+ DAI(MIXER1 RX5),
+ DAI(MIXER1 RX6),
+ DAI(MIXER1 RX7),
+ DAI(MIXER1 RX8),
+ DAI(MIXER1 RX9),
+ DAI(MIXER1 RX10),
+ DAI(MIXER1 TX1),
+ DAI(MIXER1 TX2),
+ DAI(MIXER1 TX3),
+ DAI(MIXER1 TX4),
+ DAI(MIXER1 TX5),
+ /* XBAR -> ASRC -> XBAR */
+ DAI(ASRC1 RX1),
+ DAI(ASRC1 TX1),
+ DAI(ASRC1 RX2),
+ DAI(ASRC1 TX2),
+ DAI(ASRC1 RX3),
+ DAI(ASRC1 TX3),
+ DAI(ASRC1 RX4),
+ DAI(ASRC1 TX4),
+ DAI(ASRC1 RX5),
+ DAI(ASRC1 TX5),
+ DAI(ASRC1 RX6),
+ DAI(ASRC1 TX6),
+ DAI(ASRC1 RX7),
+ /* XBAR -> OPE -> XBAR */
+ DAI(OPE1 RX),
+ DAI(OPE1 TX),
+};
+
static const char * const tegra210_ahub_mux_texts[] = {
"None",
"ADMAIF1",
@@ -421,6 +579,100 @@ static const char * const tegra186_ahub_mux_texts[] = {
"OPE1",
};
+static const char * const tegra264_ahub_mux_texts[] = {
+ "None",
+ "ADMAIF1",
+ "ADMAIF2",
+ "ADMAIF3",
+ "ADMAIF4",
+ "ADMAIF5",
+ "ADMAIF6",
+ "ADMAIF7",
+ "ADMAIF8",
+ "ADMAIF9",
+ "ADMAIF10",
+ "ADMAIF11",
+ "ADMAIF12",
+ "ADMAIF13",
+ "ADMAIF14",
+ "ADMAIF15",
+ "ADMAIF16",
+ "I2S1",
+ "I2S2",
+ "I2S3",
+ "I2S4",
+ "I2S5",
+ "I2S6",
+ "I2S7",
+ "I2S8",
+ "SFC1",
+ "SFC2",
+ "SFC3",
+ "SFC4",
+ "MIXER1 TX1",
+ "MIXER1 TX2",
+ "MIXER1 TX3",
+ "MIXER1 TX4",
+ "MIXER1 TX5",
+ "AMX1",
+ "AMX2",
+ "AMX3",
+ "AMX4",
+ "AMX5",
+ "AMX6",
+ "OPE1",
+ "MVC1",
+ "MVC2",
+ "DMIC1",
+ "DMIC2",
+ "ADX1 TX1",
+ "ADX1 TX2",
+ "ADX1 TX3",
+ "ADX1 TX4",
+ "ADX2 TX1",
+ "ADX2 TX2",
+ "ADX2 TX3",
+ "ADX2 TX4",
+ "ADX3 TX1",
+ "ADX3 TX2",
+ "ADX3 TX3",
+ "ADX3 TX4",
+ "ADX4 TX1",
+ "ADX4 TX2",
+ "ADX4 TX3",
+ "ADX4 TX4",
+ "ADX5 TX1",
+ "ADX5 TX2",
+ "ADX5 TX3",
+ "ADX5 TX4",
+ "ADX6 TX1",
+ "ADX6 TX2",
+ "ADX6 TX3",
+ "ADX6 TX4",
+ "ASRC1 TX1",
+ "ASRC1 TX2",
+ "ASRC1 TX3",
+ "ASRC1 TX4",
+ "ASRC1 TX5",
+ "ASRC1 TX6",
+ "ADMAIF17",
+ "ADMAIF18",
+ "ADMAIF19",
+ "ADMAIF20",
+ "ADMAIF21",
+ "ADMAIF22",
+ "ADMAIF23",
+ "ADMAIF24",
+ "ADMAIF25",
+ "ADMAIF26",
+ "ADMAIF27",
+ "ADMAIF28",
+ "ADMAIF29",
+ "ADMAIF30",
+ "ADMAIF31",
+ "ADMAIF32",
+};
+
static const unsigned int tegra210_ahub_mux_values[] = {
0,
/* ADMAIF */
@@ -558,6 +810,111 @@ static const unsigned int tegra186_ahub_mux_values[] = {
MUX_VALUE(2, 0),
};
+static const unsigned int tegra264_ahub_mux_values[] = {
+ 0,
+ /* ADMAIF */
+ MUX_VALUE(0, 0),
+ MUX_VALUE(0, 1),
+ MUX_VALUE(0, 2),
+ MUX_VALUE(0, 3),
+ MUX_VALUE(0, 4),
+ MUX_VALUE(0, 5),
+ MUX_VALUE(0, 6),
+ MUX_VALUE(0, 7),
+ MUX_VALUE(0, 8),
+ MUX_VALUE(0, 9),
+ MUX_VALUE(0, 10),
+ MUX_VALUE(0, 11),
+ MUX_VALUE(0, 12),
+ MUX_VALUE(0, 13),
+ MUX_VALUE(0, 14),
+ MUX_VALUE(0, 15),
+ /* I2S */
+ MUX_VALUE(0, 16),
+ MUX_VALUE(0, 17),
+ MUX_VALUE(0, 18),
+ MUX_VALUE(0, 19),
+ MUX_VALUE(0, 20),
+ MUX_VALUE(0, 21),
+ MUX_VALUE(0, 22),
+ MUX_VALUE(0, 23),
+ /* SFC */
+ MUX_VALUE(0, 24),
+ MUX_VALUE(0, 25),
+ MUX_VALUE(0, 26),
+ MUX_VALUE(0, 27),
+ /* MIXER */
+ MUX_VALUE(1, 0),
+ MUX_VALUE(1, 1),
+ MUX_VALUE(1, 2),
+ MUX_VALUE(1, 3),
+ MUX_VALUE(1, 4),
+ /* AMX */
+ MUX_VALUE(1, 8),
+ MUX_VALUE(1, 9),
+ MUX_VALUE(1, 10),
+ MUX_VALUE(1, 11),
+ MUX_VALUE(1, 12),
+ MUX_VALUE(1, 13),
+ /* OPE */
+ MUX_VALUE(2, 0),
+ /* MVC */
+ MUX_VALUE(2, 8),
+ MUX_VALUE(2, 9),
+ /* DMIC */
+ MUX_VALUE(2, 18),
+ MUX_VALUE(2, 19),
+ /* ADX */
+ MUX_VALUE(2, 24),
+ MUX_VALUE(2, 25),
+ MUX_VALUE(2, 26),
+ MUX_VALUE(2, 27),
+ MUX_VALUE(2, 28),
+ MUX_VALUE(2, 29),
+ MUX_VALUE(2, 30),
+ MUX_VALUE(2, 31),
+ MUX_VALUE(3, 0),
+ MUX_VALUE(3, 1),
+ MUX_VALUE(3, 2),
+ MUX_VALUE(3, 3),
+ MUX_VALUE(3, 4),
+ MUX_VALUE(3, 5),
+ MUX_VALUE(3, 6),
+ MUX_VALUE(3, 7),
+ MUX_VALUE(3, 8),
+ MUX_VALUE(3, 9),
+ MUX_VALUE(3, 10),
+ MUX_VALUE(3, 11),
+ MUX_VALUE(3, 12),
+ MUX_VALUE(3, 13),
+ MUX_VALUE(3, 14),
+ MUX_VALUE(3, 15),
+ /* ASRC */
+ MUX_VALUE(3, 24),
+ MUX_VALUE(3, 25),
+ MUX_VALUE(3, 26),
+ MUX_VALUE(3, 27),
+ MUX_VALUE(3, 28),
+ MUX_VALUE(3, 29),
+ /* ADMAIF */
+ MUX_VALUE(4, 7),
+ MUX_VALUE(4, 8),
+ MUX_VALUE(4, 9),
+ MUX_VALUE(4, 10),
+ MUX_VALUE(4, 11),
+ MUX_VALUE(4, 12),
+ MUX_VALUE(4, 13),
+ MUX_VALUE(4, 14),
+ MUX_VALUE(4, 15),
+ MUX_VALUE(4, 16),
+ MUX_VALUE(4, 17),
+ MUX_VALUE(4, 18),
+ MUX_VALUE(4, 19),
+ MUX_VALUE(4, 20),
+ MUX_VALUE(4, 21),
+ MUX_VALUE(4, 22),
+};
+
/* Controls for t210 */
MUX_ENUM_CTRL_DECL(t210_admaif1_tx, 0x00);
MUX_ENUM_CTRL_DECL(t210_admaif2_tx, 0x01);
@@ -712,6 +1069,103 @@ MUX_ENUM_CTRL_DECL_234(t234_asrc15_tx, 0x68);
MUX_ENUM_CTRL_DECL_234(t234_asrc16_tx, 0x69);
MUX_ENUM_CTRL_DECL_234(t234_asrc17_tx, 0x6a);
+/* Controls for t264 */
+MUX_ENUM_CTRL_DECL_264(t264_admaif1_tx, 0x00);
+MUX_ENUM_CTRL_DECL_264(t264_admaif2_tx, 0x01);
+MUX_ENUM_CTRL_DECL_264(t264_admaif3_tx, 0x02);
+MUX_ENUM_CTRL_DECL_264(t264_admaif4_tx, 0x03);
+MUX_ENUM_CTRL_DECL_264(t264_admaif5_tx, 0x04);
+MUX_ENUM_CTRL_DECL_264(t264_admaif6_tx, 0x05);
+MUX_ENUM_CTRL_DECL_264(t264_admaif7_tx, 0x06);
+MUX_ENUM_CTRL_DECL_264(t264_admaif8_tx, 0x07);
+MUX_ENUM_CTRL_DECL_264(t264_admaif9_tx, 0x08);
+MUX_ENUM_CTRL_DECL_264(t264_admaif10_tx, 0x09);
+MUX_ENUM_CTRL_DECL_264(t264_admaif11_tx, 0x0a);
+MUX_ENUM_CTRL_DECL_264(t264_admaif12_tx, 0x0b);
+MUX_ENUM_CTRL_DECL_264(t264_admaif13_tx, 0x0c);
+MUX_ENUM_CTRL_DECL_264(t264_admaif14_tx, 0x0d);
+MUX_ENUM_CTRL_DECL_264(t264_admaif15_tx, 0x0e);
+MUX_ENUM_CTRL_DECL_264(t264_admaif16_tx, 0x0f);
+MUX_ENUM_CTRL_DECL_264(t264_i2s1_tx, 0x10);
+MUX_ENUM_CTRL_DECL_264(t264_i2s2_tx, 0x11);
+MUX_ENUM_CTRL_DECL_264(t264_i2s3_tx, 0x12);
+MUX_ENUM_CTRL_DECL_264(t264_i2s4_tx, 0x13);
+MUX_ENUM_CTRL_DECL_264(t264_i2s5_tx, 0x14);
+MUX_ENUM_CTRL_DECL_264(t264_i2s6_tx, 0x15);
+MUX_ENUM_CTRL_DECL_264(t264_i2s7_tx, 0x16);
+MUX_ENUM_CTRL_DECL_264(t264_i2s8_tx, 0x17);
+MUX_ENUM_CTRL_DECL_264(t264_sfc1_tx, 0x18);
+MUX_ENUM_CTRL_DECL_264(t264_sfc2_tx, 0x19);
+MUX_ENUM_CTRL_DECL_264(t264_sfc3_tx, 0x1a);
+MUX_ENUM_CTRL_DECL_264(t264_sfc4_tx, 0x1b);
+MUX_ENUM_CTRL_DECL_264(t264_mixer11_tx, 0x20);
+MUX_ENUM_CTRL_DECL_264(t264_mixer12_tx, 0x21);
+MUX_ENUM_CTRL_DECL_264(t264_mixer13_tx, 0x22);
+MUX_ENUM_CTRL_DECL_264(t264_mixer14_tx, 0x23);
+MUX_ENUM_CTRL_DECL_264(t264_mixer15_tx, 0x24);
+MUX_ENUM_CTRL_DECL_264(t264_mixer16_tx, 0x25);
+MUX_ENUM_CTRL_DECL_264(t264_mixer17_tx, 0x26);
+MUX_ENUM_CTRL_DECL_264(t264_mixer18_tx, 0x27);
+MUX_ENUM_CTRL_DECL_264(t264_mixer19_tx, 0x28);
+MUX_ENUM_CTRL_DECL_264(t264_mixer110_tx, 0x29);
+MUX_ENUM_CTRL_DECL_264(t264_dspk1_tx, 0x30);
+MUX_ENUM_CTRL_DECL_264(t264_ope1_tx, 0x40);
+MUX_ENUM_CTRL_DECL_264(t264_mvc1_tx, 0x44);
+MUX_ENUM_CTRL_DECL_264(t264_mvc2_tx, 0x45);
+MUX_ENUM_CTRL_DECL_264(t264_amx11_tx, 0x48);
+MUX_ENUM_CTRL_DECL_264(t264_amx12_tx, 0x49);
+MUX_ENUM_CTRL_DECL_264(t264_amx13_tx, 0x4a);
+MUX_ENUM_CTRL_DECL_264(t264_amx14_tx, 0x4b);
+MUX_ENUM_CTRL_DECL_264(t264_amx21_tx, 0x4c);
+MUX_ENUM_CTRL_DECL_264(t264_amx22_tx, 0x4d);
+MUX_ENUM_CTRL_DECL_264(t264_amx23_tx, 0x4e);
+MUX_ENUM_CTRL_DECL_264(t264_amx24_tx, 0x4f);
+MUX_ENUM_CTRL_DECL_264(t264_amx31_tx, 0x50);
+MUX_ENUM_CTRL_DECL_264(t264_amx32_tx, 0x51);
+MUX_ENUM_CTRL_DECL_264(t264_amx33_tx, 0x52);
+MUX_ENUM_CTRL_DECL_264(t264_amx34_tx, 0x53);
+MUX_ENUM_CTRL_DECL_264(t264_adx1_tx, 0x58);
+MUX_ENUM_CTRL_DECL_264(t264_adx2_tx, 0x59);
+MUX_ENUM_CTRL_DECL_264(t264_adx3_tx, 0x5a);
+MUX_ENUM_CTRL_DECL_264(t264_adx4_tx, 0x5b);
+MUX_ENUM_CTRL_DECL_264(t264_amx41_tx, 0x5c);
+MUX_ENUM_CTRL_DECL_264(t264_amx42_tx, 0x5d);
+MUX_ENUM_CTRL_DECL_264(t264_amx43_tx, 0x5e);
+MUX_ENUM_CTRL_DECL_264(t264_amx44_tx, 0x5f);
+MUX_ENUM_CTRL_DECL_264(t264_admaif17_tx, 0x60);
+MUX_ENUM_CTRL_DECL_264(t264_admaif18_tx, 0x61);
+MUX_ENUM_CTRL_DECL_264(t264_admaif19_tx, 0x62);
+MUX_ENUM_CTRL_DECL_264(t264_admaif20_tx, 0x63);
+MUX_ENUM_CTRL_DECL_264(t264_asrc11_tx, 0x64);
+MUX_ENUM_CTRL_DECL_264(t264_asrc12_tx, 0x65);
+MUX_ENUM_CTRL_DECL_264(t264_asrc13_tx, 0x66);
+MUX_ENUM_CTRL_DECL_264(t264_asrc14_tx, 0x67);
+MUX_ENUM_CTRL_DECL_264(t264_asrc15_tx, 0x68);
+MUX_ENUM_CTRL_DECL_264(t264_asrc16_tx, 0x69);
+MUX_ENUM_CTRL_DECL_264(t264_asrc17_tx, 0x6a);
+MUX_ENUM_CTRL_DECL_264(t264_admaif21_tx, 0x74);
+MUX_ENUM_CTRL_DECL_264(t264_admaif22_tx, 0x75);
+MUX_ENUM_CTRL_DECL_264(t264_admaif23_tx, 0x76);
+MUX_ENUM_CTRL_DECL_264(t264_admaif24_tx, 0x77);
+MUX_ENUM_CTRL_DECL_264(t264_admaif25_tx, 0x78);
+MUX_ENUM_CTRL_DECL_264(t264_admaif26_tx, 0x79);
+MUX_ENUM_CTRL_DECL_264(t264_admaif27_tx, 0x7a);
+MUX_ENUM_CTRL_DECL_264(t264_admaif28_tx, 0x7b);
+MUX_ENUM_CTRL_DECL_264(t264_admaif29_tx, 0x7c);
+MUX_ENUM_CTRL_DECL_264(t264_admaif30_tx, 0x7d);
+MUX_ENUM_CTRL_DECL_264(t264_admaif31_tx, 0x7e);
+MUX_ENUM_CTRL_DECL_264(t264_admaif32_tx, 0x7f);
+MUX_ENUM_CTRL_DECL_264(t264_amx51_tx, 0x80);
+MUX_ENUM_CTRL_DECL_264(t264_amx52_tx, 0x81);
+MUX_ENUM_CTRL_DECL_264(t264_amx53_tx, 0x82);
+MUX_ENUM_CTRL_DECL_264(t264_amx54_tx, 0x83);
+MUX_ENUM_CTRL_DECL_264(t264_amx61_tx, 0x84);
+MUX_ENUM_CTRL_DECL_264(t264_amx62_tx, 0x85);
+MUX_ENUM_CTRL_DECL_264(t264_amx63_tx, 0x86);
+MUX_ENUM_CTRL_DECL_264(t264_amx64_tx, 0x87);
+MUX_ENUM_CTRL_DECL_264(t264_adx5_tx, 0x88);
+MUX_ENUM_CTRL_DECL_264(t264_adx6_tx, 0x89);
+
static const struct snd_soc_dapm_widget tegra210_ahub_widgets[] = {
WIDGETS("ADMAIF1", t210_admaif1_tx),
WIDGETS("ADMAIF2", t210_admaif2_tx),
@@ -996,6 +1450,147 @@ static const struct snd_soc_dapm_widget tegra234_ahub_widgets[] = {
WIDGETS("OPE1", t186_ope1_tx),
};
+static const struct snd_soc_dapm_widget tegra264_ahub_widgets[] = {
+ WIDGETS("ADMAIF1", t264_admaif1_tx),
+ WIDGETS("ADMAIF2", t264_admaif2_tx),
+ WIDGETS("ADMAIF3", t264_admaif3_tx),
+ WIDGETS("ADMAIF4", t264_admaif4_tx),
+ WIDGETS("ADMAIF5", t264_admaif5_tx),
+ WIDGETS("ADMAIF6", t264_admaif6_tx),
+ WIDGETS("ADMAIF7", t264_admaif7_tx),
+ WIDGETS("ADMAIF8", t264_admaif8_tx),
+ WIDGETS("ADMAIF9", t264_admaif9_tx),
+ WIDGETS("ADMAIF10", t264_admaif10_tx),
+ WIDGETS("ADMAIF11", t264_admaif11_tx),
+ WIDGETS("ADMAIF12", t264_admaif12_tx),
+ WIDGETS("ADMAIF13", t264_admaif13_tx),
+ WIDGETS("ADMAIF14", t264_admaif14_tx),
+ WIDGETS("ADMAIF15", t264_admaif15_tx),
+ WIDGETS("ADMAIF16", t264_admaif16_tx),
+ WIDGETS("ADMAIF17", t264_admaif17_tx),
+ WIDGETS("ADMAIF18", t264_admaif18_tx),
+ WIDGETS("ADMAIF19", t264_admaif19_tx),
+ WIDGETS("ADMAIF20", t264_admaif20_tx),
+ WIDGETS("ADMAIF21", t264_admaif21_tx),
+ WIDGETS("ADMAIF22", t264_admaif22_tx),
+ WIDGETS("ADMAIF23", t264_admaif23_tx),
+ WIDGETS("ADMAIF24", t264_admaif24_tx),
+ WIDGETS("ADMAIF25", t264_admaif25_tx),
+ WIDGETS("ADMAIF26", t264_admaif26_tx),
+ WIDGETS("ADMAIF27", t264_admaif27_tx),
+ WIDGETS("ADMAIF28", t264_admaif28_tx),
+ WIDGETS("ADMAIF29", t264_admaif29_tx),
+ WIDGETS("ADMAIF30", t264_admaif30_tx),
+ WIDGETS("ADMAIF31", t264_admaif31_tx),
+ WIDGETS("ADMAIF32", t264_admaif32_tx),
+ WIDGETS("I2S1", t264_i2s1_tx),
+ WIDGETS("I2S2", t264_i2s2_tx),
+ WIDGETS("I2S3", t264_i2s3_tx),
+ WIDGETS("I2S4", t264_i2s4_tx),
+ WIDGETS("I2S5", t264_i2s5_tx),
+ WIDGETS("I2S6", t264_i2s6_tx),
+ WIDGETS("I2S7", t264_i2s7_tx),
+ WIDGETS("I2S8", t264_i2s8_tx),
+ TX_WIDGETS("DMIC1"),
+ TX_WIDGETS("DMIC2"),
+ WIDGETS("DSPK1", t264_dspk1_tx),
+ WIDGETS("SFC1", t264_sfc1_tx),
+ WIDGETS("SFC2", t264_sfc2_tx),
+ WIDGETS("SFC3", t264_sfc3_tx),
+ WIDGETS("SFC4", t264_sfc4_tx),
+ WIDGETS("MVC1", t264_mvc1_tx),
+ WIDGETS("MVC2", t264_mvc2_tx),
+ WIDGETS("AMX1 RX1", t264_amx11_tx),
+ WIDGETS("AMX1 RX2", t264_amx12_tx),
+ WIDGETS("AMX1 RX3", t264_amx13_tx),
+ WIDGETS("AMX1 RX4", t264_amx14_tx),
+ WIDGETS("AMX2 RX1", t264_amx21_tx),
+ WIDGETS("AMX2 RX2", t264_amx22_tx),
+ WIDGETS("AMX2 RX3", t264_amx23_tx),
+ WIDGETS("AMX2 RX4", t264_amx24_tx),
+ WIDGETS("AMX3 RX1", t264_amx31_tx),
+ WIDGETS("AMX3 RX2", t264_amx32_tx),
+ WIDGETS("AMX3 RX3", t264_amx33_tx),
+ WIDGETS("AMX3 RX4", t264_amx34_tx),
+ WIDGETS("AMX4 RX1", t264_amx41_tx),
+ WIDGETS("AMX4 RX2", t264_amx42_tx),
+ WIDGETS("AMX4 RX3", t264_amx43_tx),
+ WIDGETS("AMX4 RX4", t264_amx44_tx),
+ WIDGETS("AMX5 RX1", t264_amx51_tx),
+ WIDGETS("AMX5 RX2", t264_amx52_tx),
+ WIDGETS("AMX5 RX3", t264_amx53_tx),
+ WIDGETS("AMX5 RX4", t264_amx54_tx),
+ WIDGETS("AMX6 RX1", t264_amx61_tx),
+ WIDGETS("AMX6 RX2", t264_amx62_tx),
+ WIDGETS("AMX6 RX3", t264_amx63_tx),
+ WIDGETS("AMX6 RX4", t264_amx64_tx),
+ TX_WIDGETS("AMX1"),
+ TX_WIDGETS("AMX2"),
+ TX_WIDGETS("AMX3"),
+ TX_WIDGETS("AMX4"),
+ TX_WIDGETS("AMX5"),
+ TX_WIDGETS("AMX6"),
+ WIDGETS("ADX1", t264_adx1_tx),
+ WIDGETS("ADX2", t264_adx2_tx),
+ WIDGETS("ADX3", t264_adx3_tx),
+ WIDGETS("ADX4", t264_adx4_tx),
+ WIDGETS("ADX5", t264_adx5_tx),
+ WIDGETS("ADX6", t264_adx6_tx),
+ TX_WIDGETS("ADX1 TX1"),
+ TX_WIDGETS("ADX1 TX2"),
+ TX_WIDGETS("ADX1 TX3"),
+ TX_WIDGETS("ADX1 TX4"),
+ TX_WIDGETS("ADX2 TX1"),
+ TX_WIDGETS("ADX2 TX2"),
+ TX_WIDGETS("ADX2 TX3"),
+ TX_WIDGETS("ADX2 TX4"),
+ TX_WIDGETS("ADX3 TX1"),
+ TX_WIDGETS("ADX3 TX2"),
+ TX_WIDGETS("ADX3 TX3"),
+ TX_WIDGETS("ADX3 TX4"),
+ TX_WIDGETS("ADX4 TX1"),
+ TX_WIDGETS("ADX4 TX2"),
+ TX_WIDGETS("ADX4 TX3"),
+ TX_WIDGETS("ADX4 TX4"),
+ TX_WIDGETS("ADX5 TX1"),
+ TX_WIDGETS("ADX5 TX2"),
+ TX_WIDGETS("ADX5 TX3"),
+ TX_WIDGETS("ADX5 TX4"),
+ TX_WIDGETS("ADX6 TX1"),
+ TX_WIDGETS("ADX6 TX2"),
+ TX_WIDGETS("ADX6 TX3"),
+ TX_WIDGETS("ADX6 TX4"),
+ WIDGETS("MIXER1 RX1", t264_mixer11_tx),
+ WIDGETS("MIXER1 RX2", t264_mixer12_tx),
+ WIDGETS("MIXER1 RX3", t264_mixer13_tx),
+ WIDGETS("MIXER1 RX4", t264_mixer14_tx),
+ WIDGETS("MIXER1 RX5", t264_mixer15_tx),
+ WIDGETS("MIXER1 RX6", t264_mixer16_tx),
+ WIDGETS("MIXER1 RX7", t264_mixer17_tx),
+ WIDGETS("MIXER1 RX8", t264_mixer18_tx),
+ WIDGETS("MIXER1 RX9", t264_mixer19_tx),
+ WIDGETS("MIXER1 RX10", t264_mixer110_tx),
+ TX_WIDGETS("MIXER1 TX1"),
+ TX_WIDGETS("MIXER1 TX2"),
+ TX_WIDGETS("MIXER1 TX3"),
+ TX_WIDGETS("MIXER1 TX4"),
+ TX_WIDGETS("MIXER1 TX5"),
+ WIDGETS("ASRC1 RX1", t264_asrc11_tx),
+ WIDGETS("ASRC1 RX2", t264_asrc12_tx),
+ WIDGETS("ASRC1 RX3", t264_asrc13_tx),
+ WIDGETS("ASRC1 RX4", t264_asrc14_tx),
+ WIDGETS("ASRC1 RX5", t264_asrc15_tx),
+ WIDGETS("ASRC1 RX6", t264_asrc16_tx),
+ WIDGETS("ASRC1 RX7", t264_asrc17_tx),
+ TX_WIDGETS("ASRC1 TX1"),
+ TX_WIDGETS("ASRC1 TX2"),
+ TX_WIDGETS("ASRC1 TX3"),
+ TX_WIDGETS("ASRC1 TX4"),
+ TX_WIDGETS("ASRC1 TX5"),
+ TX_WIDGETS("ASRC1 TX6"),
+ WIDGETS("OPE1", t264_ope1_tx),
+};
+
#define TEGRA_COMMON_MUX_ROUTES(name) \
{ name " XBAR-TX", NULL, name " Mux" }, \
{ name " Mux", "ADMAIF1", "ADMAIF1 XBAR-RX" }, \
@@ -1015,7 +1610,6 @@ static const struct snd_soc_dapm_widget tegra234_ahub_widgets[] = {
{ name " Mux", "I2S5", "I2S5 XBAR-RX" }, \
{ name " Mux", "DMIC1", "DMIC1 XBAR-RX" }, \
{ name " Mux", "DMIC2", "DMIC2 XBAR-RX" }, \
- { name " Mux", "DMIC3", "DMIC3 XBAR-RX" }, \
{ name " Mux", "SFC1", "SFC1 XBAR-RX" }, \
{ name " Mux", "SFC2", "SFC2 XBAR-RX" }, \
{ name " Mux", "SFC3", "SFC3 XBAR-RX" }, \
@@ -1040,6 +1634,7 @@ static const struct snd_soc_dapm_widget tegra234_ahub_widgets[] = {
{ name " Mux", "OPE1", "OPE1 XBAR-RX" },
#define TEGRA210_ONLY_MUX_ROUTES(name) \
+ { name " Mux", "DMIC3", "DMIC3 XBAR-RX" }, \
{ name " Mux", "OPE2", "OPE2 XBAR-RX" },
#define TEGRA186_ONLY_MUX_ROUTES(name) \
@@ -1054,6 +1649,7 @@ static const struct snd_soc_dapm_widget tegra234_ahub_widgets[] = {
{ name " Mux", "ADMAIF19", "ADMAIF19 XBAR-RX" }, \
{ name " Mux", "ADMAIF20", "ADMAIF20 XBAR-RX" }, \
{ name " Mux", "I2S6", "I2S6 XBAR-RX" }, \
+ { name " Mux", "DMIC3", "DMIC3 XBAR-RX" }, \
{ name " Mux", "DMIC4", "DMIC4 XBAR-RX" }, \
{ name " Mux", "AMX3", "AMX3 XBAR-RX" }, \
{ name " Mux", "AMX4", "AMX4 XBAR-RX" }, \
@@ -1072,6 +1668,59 @@ static const struct snd_soc_dapm_widget tegra234_ahub_widgets[] = {
{ name " Mux", "ASRC1 TX5", "ASRC1 TX5 XBAR-RX" }, \
{ name " Mux", "ASRC1 TX6", "ASRC1 TX6 XBAR-RX" },
+#define TEGRA264_ONLY_MUX_ROUTES(name) \
+ { name " Mux", "ADMAIF11", "ADMAIF11 XBAR-RX" }, \
+ { name " Mux", "ADMAIF12", "ADMAIF12 XBAR-RX" }, \
+ { name " Mux", "ADMAIF13", "ADMAIF13 XBAR-RX" }, \
+ { name " Mux", "ADMAIF14", "ADMAIF14 XBAR-RX" }, \
+ { name " Mux", "ADMAIF15", "ADMAIF15 XBAR-RX" }, \
+ { name " Mux", "ADMAIF16", "ADMAIF16 XBAR-RX" }, \
+ { name " Mux", "ADMAIF17", "ADMAIF17 XBAR-RX" }, \
+ { name " Mux", "ADMAIF18", "ADMAIF18 XBAR-RX" }, \
+ { name " Mux", "ADMAIF19", "ADMAIF19 XBAR-RX" }, \
+ { name " Mux", "ADMAIF20", "ADMAIF20 XBAR-RX" }, \
+ { name " Mux", "ADMAIF21", "ADMAIF21 XBAR-RX" }, \
+ { name " Mux", "ADMAIF22", "ADMAIF22 XBAR-RX" }, \
+ { name " Mux", "ADMAIF23", "ADMAIF23 XBAR-RX" }, \
+ { name " Mux", "ADMAIF24", "ADMAIF24 XBAR-RX" }, \
+ { name " Mux", "ADMAIF25", "ADMAIF25 XBAR-RX" }, \
+ { name " Mux", "ADMAIF26", "ADMAIF26 XBAR-RX" }, \
+ { name " Mux", "ADMAIF27", "ADMAIF27 XBAR-RX" }, \
+ { name " Mux", "ADMAIF28", "ADMAIF28 XBAR-RX" }, \
+ { name " Mux", "ADMAIF29", "ADMAIF29 XBAR-RX" }, \
+ { name " Mux", "ADMAIF30", "ADMAIF30 XBAR-RX" }, \
+ { name " Mux", "ADMAIF31", "ADMAIF31 XBAR-RX" }, \
+ { name " Mux", "ADMAIF32", "ADMAIF32 XBAR-RX" }, \
+ { name " Mux", "I2S6", "I2S6 XBAR-RX" }, \
+ { name " Mux", "I2S7", "I2S7 XBAR-RX" }, \
+ { name " Mux", "I2S8", "I2S8 XBAR-RX" }, \
+ { name " Mux", "AMX3", "AMX3 XBAR-RX" }, \
+ { name " Mux", "AMX4", "AMX4 XBAR-RX" }, \
+ { name " Mux", "AMX5", "AMX5 XBAR-RX" }, \
+ { name " Mux", "AMX6", "AMX6 XBAR-RX" }, \
+ { name " Mux", "ADX3 TX1", "ADX3 TX1 XBAR-RX" }, \
+ { name " Mux", "ADX3 TX2", "ADX3 TX2 XBAR-RX" }, \
+ { name " Mux", "ADX3 TX3", "ADX3 TX3 XBAR-RX" }, \
+ { name " Mux", "ADX3 TX4", "ADX3 TX4 XBAR-RX" }, \
+ { name " Mux", "ADX4 TX1", "ADX4 TX1 XBAR-RX" }, \
+ { name " Mux", "ADX4 TX2", "ADX4 TX2 XBAR-RX" }, \
+ { name " Mux", "ADX4 TX3", "ADX4 TX3 XBAR-RX" }, \
+ { name " Mux", "ADX4 TX4", "ADX4 TX4 XBAR-RX" }, \
+ { name " Mux", "ADX5 TX1", "ADX5 TX1 XBAR-RX" }, \
+ { name " Mux", "ADX5 TX2", "ADX5 TX2 XBAR-RX" }, \
+ { name " Mux", "ADX5 TX3", "ADX5 TX3 XBAR-RX" }, \
+ { name " Mux", "ADX5 TX4", "ADX5 TX4 XBAR-RX" }, \
+ { name " Mux", "ADX6 TX1", "ADX6 TX1 XBAR-RX" }, \
+ { name " Mux", "ADX6 TX2", "ADX6 TX2 XBAR-RX" }, \
+ { name " Mux", "ADX6 TX3", "ADX6 TX3 XBAR-RX" }, \
+ { name " Mux", "ADX6 TX4", "ADX6 TX4 XBAR-RX" }, \
+ { name " Mux", "ASRC1 TX1", "ASRC1 TX1 XBAR-RX" }, \
+ { name " Mux", "ASRC1 TX2", "ASRC1 TX2 XBAR-RX" }, \
+ { name " Mux", "ASRC1 TX3", "ASRC1 TX3 XBAR-RX" }, \
+ { name " Mux", "ASRC1 TX4", "ASRC1 TX4 XBAR-RX" }, \
+ { name " Mux", "ASRC1 TX5", "ASRC1 TX5 XBAR-RX" }, \
+ { name " Mux", "ASRC1 TX6", "ASRC1 TX6 XBAR-RX" },
+
#define TEGRA210_MUX_ROUTES(name) \
TEGRA_COMMON_MUX_ROUTES(name) \
TEGRA210_ONLY_MUX_ROUTES(name)
@@ -1080,6 +1729,10 @@ static const struct snd_soc_dapm_widget tegra234_ahub_widgets[] = {
TEGRA_COMMON_MUX_ROUTES(name) \
TEGRA186_ONLY_MUX_ROUTES(name)
+#define TEGRA264_MUX_ROUTES(name) \
+ TEGRA_COMMON_MUX_ROUTES(name) \
+ TEGRA264_ONLY_MUX_ROUTES(name)
+
/* Connect FEs with XBAR */
#define TEGRA_FE_ROUTES(name) \
{ name " XBAR-Playback", NULL, name " Playback" }, \
@@ -1238,6 +1891,136 @@ static const struct snd_soc_dapm_route tegra186_ahub_routes[] = {
TEGRA186_MUX_ROUTES("OPE1")
};
+static const struct snd_soc_dapm_route tegra264_ahub_routes[] = {
+ TEGRA_FE_ROUTES("ADMAIF1")
+ TEGRA_FE_ROUTES("ADMAIF2")
+ TEGRA_FE_ROUTES("ADMAIF3")
+ TEGRA_FE_ROUTES("ADMAIF4")
+ TEGRA_FE_ROUTES("ADMAIF5")
+ TEGRA_FE_ROUTES("ADMAIF6")
+ TEGRA_FE_ROUTES("ADMAIF7")
+ TEGRA_FE_ROUTES("ADMAIF8")
+ TEGRA_FE_ROUTES("ADMAIF9")
+ TEGRA_FE_ROUTES("ADMAIF10")
+ TEGRA_FE_ROUTES("ADMAIF11")
+ TEGRA_FE_ROUTES("ADMAIF12")
+ TEGRA_FE_ROUTES("ADMAIF13")
+ TEGRA_FE_ROUTES("ADMAIF14")
+ TEGRA_FE_ROUTES("ADMAIF15")
+ TEGRA_FE_ROUTES("ADMAIF16")
+ TEGRA_FE_ROUTES("ADMAIF17")
+ TEGRA_FE_ROUTES("ADMAIF18")
+ TEGRA_FE_ROUTES("ADMAIF19")
+ TEGRA_FE_ROUTES("ADMAIF20")
+ TEGRA_FE_ROUTES("ADMAIF21")
+ TEGRA_FE_ROUTES("ADMAIF22")
+ TEGRA_FE_ROUTES("ADMAIF23")
+ TEGRA_FE_ROUTES("ADMAIF24")
+ TEGRA_FE_ROUTES("ADMAIF25")
+ TEGRA_FE_ROUTES("ADMAIF26")
+ TEGRA_FE_ROUTES("ADMAIF27")
+ TEGRA_FE_ROUTES("ADMAIF28")
+ TEGRA_FE_ROUTES("ADMAIF29")
+ TEGRA_FE_ROUTES("ADMAIF30")
+ TEGRA_FE_ROUTES("ADMAIF31")
+ TEGRA_FE_ROUTES("ADMAIF32")
+ TEGRA264_MUX_ROUTES("ADMAIF1")
+ TEGRA264_MUX_ROUTES("ADMAIF2")
+ TEGRA264_MUX_ROUTES("ADMAIF3")
+ TEGRA264_MUX_ROUTES("ADMAIF4")
+ TEGRA264_MUX_ROUTES("ADMAIF5")
+ TEGRA264_MUX_ROUTES("ADMAIF6")
+ TEGRA264_MUX_ROUTES("ADMAIF7")
+ TEGRA264_MUX_ROUTES("ADMAIF8")
+ TEGRA264_MUX_ROUTES("ADMAIF9")
+ TEGRA264_MUX_ROUTES("ADMAIF10")
+ TEGRA264_MUX_ROUTES("ADMAIF11")
+ TEGRA264_MUX_ROUTES("ADMAIF12")
+ TEGRA264_MUX_ROUTES("ADMAIF13")
+ TEGRA264_MUX_ROUTES("ADMAIF14")
+ TEGRA264_MUX_ROUTES("ADMAIF15")
+ TEGRA264_MUX_ROUTES("ADMAIF16")
+ TEGRA264_MUX_ROUTES("ADMAIF17")
+ TEGRA264_MUX_ROUTES("ADMAIF18")
+ TEGRA264_MUX_ROUTES("ADMAIF19")
+ TEGRA264_MUX_ROUTES("ADMAIF20")
+ TEGRA264_MUX_ROUTES("ADMAIF21")
+ TEGRA264_MUX_ROUTES("ADMAIF22")
+ TEGRA264_MUX_ROUTES("ADMAIF23")
+ TEGRA264_MUX_ROUTES("ADMAIF24")
+ TEGRA264_MUX_ROUTES("ADMAIF25")
+ TEGRA264_MUX_ROUTES("ADMAIF26")
+ TEGRA264_MUX_ROUTES("ADMAIF27")
+ TEGRA264_MUX_ROUTES("ADMAIF28")
+ TEGRA264_MUX_ROUTES("ADMAIF29")
+ TEGRA264_MUX_ROUTES("ADMAIF30")
+ TEGRA264_MUX_ROUTES("ADMAIF31")
+ TEGRA264_MUX_ROUTES("ADMAIF32")
+ TEGRA264_MUX_ROUTES("I2S1")
+ TEGRA264_MUX_ROUTES("I2S2")
+ TEGRA264_MUX_ROUTES("I2S3")
+ TEGRA264_MUX_ROUTES("I2S4")
+ TEGRA264_MUX_ROUTES("I2S5")
+ TEGRA264_MUX_ROUTES("I2S6")
+ TEGRA264_MUX_ROUTES("I2S7")
+ TEGRA264_MUX_ROUTES("I2S8")
+ TEGRA264_MUX_ROUTES("DSPK1")
+ TEGRA264_MUX_ROUTES("SFC1")
+ TEGRA264_MUX_ROUTES("SFC2")
+ TEGRA264_MUX_ROUTES("SFC3")
+ TEGRA264_MUX_ROUTES("SFC4")
+ TEGRA264_MUX_ROUTES("MVC1")
+ TEGRA264_MUX_ROUTES("MVC2")
+ TEGRA264_MUX_ROUTES("AMX1 RX1")
+ TEGRA264_MUX_ROUTES("AMX1 RX2")
+ TEGRA264_MUX_ROUTES("AMX1 RX3")
+ TEGRA264_MUX_ROUTES("AMX1 RX4")
+ TEGRA264_MUX_ROUTES("AMX2 RX1")
+ TEGRA264_MUX_ROUTES("AMX2 RX2")
+ TEGRA264_MUX_ROUTES("AMX2 RX3")
+ TEGRA264_MUX_ROUTES("AMX2 RX4")
+ TEGRA264_MUX_ROUTES("AMX3 RX1")
+ TEGRA264_MUX_ROUTES("AMX3 RX2")
+ TEGRA264_MUX_ROUTES("AMX3 RX3")
+ TEGRA264_MUX_ROUTES("AMX3 RX4")
+ TEGRA264_MUX_ROUTES("AMX4 RX1")
+ TEGRA264_MUX_ROUTES("AMX4 RX2")
+ TEGRA264_MUX_ROUTES("AMX4 RX3")
+ TEGRA264_MUX_ROUTES("AMX4 RX4")
+ TEGRA264_MUX_ROUTES("AMX5 RX1")
+ TEGRA264_MUX_ROUTES("AMX5 RX2")
+ TEGRA264_MUX_ROUTES("AMX5 RX3")
+ TEGRA264_MUX_ROUTES("AMX5 RX4")
+ TEGRA264_MUX_ROUTES("AMX6 RX1")
+ TEGRA264_MUX_ROUTES("AMX6 RX2")
+ TEGRA264_MUX_ROUTES("AMX6 RX3")
+ TEGRA264_MUX_ROUTES("AMX6 RX4")
+ TEGRA264_MUX_ROUTES("ADX1")
+ TEGRA264_MUX_ROUTES("ADX2")
+ TEGRA264_MUX_ROUTES("ADX3")
+ TEGRA264_MUX_ROUTES("ADX4")
+ TEGRA264_MUX_ROUTES("ADX5")
+ TEGRA264_MUX_ROUTES("ADX6")
+ TEGRA264_MUX_ROUTES("MIXER1 RX1")
+ TEGRA264_MUX_ROUTES("MIXER1 RX2")
+ TEGRA264_MUX_ROUTES("MIXER1 RX3")
+ TEGRA264_MUX_ROUTES("MIXER1 RX4")
+ TEGRA264_MUX_ROUTES("MIXER1 RX5")
+ TEGRA264_MUX_ROUTES("MIXER1 RX6")
+ TEGRA264_MUX_ROUTES("MIXER1 RX7")
+ TEGRA264_MUX_ROUTES("MIXER1 RX8")
+ TEGRA264_MUX_ROUTES("MIXER1 RX9")
+ TEGRA264_MUX_ROUTES("MIXER1 RX10")
+ TEGRA264_MUX_ROUTES("ASRC1 RX1")
+ TEGRA264_MUX_ROUTES("ASRC1 RX2")
+ TEGRA264_MUX_ROUTES("ASRC1 RX3")
+ TEGRA264_MUX_ROUTES("ASRC1 RX4")
+ TEGRA264_MUX_ROUTES("ASRC1 RX5")
+ TEGRA264_MUX_ROUTES("ASRC1 RX6")
+ TEGRA264_MUX_ROUTES("ASRC1 RX7")
+ TEGRA264_MUX_ROUTES("OPE1")
+};
+
static const struct snd_soc_component_driver tegra210_ahub_component = {
.dapm_widgets = tegra210_ahub_widgets,
.num_dapm_widgets = ARRAY_SIZE(tegra210_ahub_widgets),
@@ -1259,6 +2042,36 @@ static const struct snd_soc_component_driver tegra234_ahub_component = {
.num_dapm_routes = ARRAY_SIZE(tegra186_ahub_routes),
};
+static const struct snd_soc_component_driver tegra264_ahub_component = {
+ .dapm_widgets = tegra264_ahub_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(tegra264_ahub_widgets),
+ .dapm_routes = tegra264_ahub_routes,
+ .num_dapm_routes = ARRAY_SIZE(tegra264_ahub_routes),
+};
+
+static bool tegra264_ahub_wr_reg(struct device *dev, unsigned int reg)
+{
+ int part;
+
+ for (part = 0; part < TEGRA264_XBAR_UPDATE_MAX_REG; part++) {
+ switch (reg & ~(part << 12)) {
+ case TEGRA264_AXBAR_ADMAIF_RX1 ... TEGRA264_AXBAR_SFC4_RX1:
+ case TEGRA264_AXBAR_MIXER1_RX1 ... TEGRA264_AXBAR_MIXER1_RX10:
+ case TEGRA264_AXBAR_DSPK1_RX1:
+ case TEGRA264_AXBAR_OPE1_RX1:
+ case TEGRA264_AXBAR_MVC1_RX1 ... TEGRA264_AXBAR_MVC2_RX1:
+ case TEGRA264_AXBAR_AMX1_RX1 ... TEGRA264_AXBAR_AMX3_RX4:
+ case TEGRA264_AXBAR_ADX1_RX1 ... TEGRA264_AXBAR_ASRC1_RX7:
+ case TEGRA264_AXBAR_ADMAIF_RX21 ... TEGRA264_AXBAR_ADX6_RX1:
+ return true;
+ default:
+ break;
+ };
+ }
+
+ return false;
+}
+
static const struct regmap_config tegra210_ahub_regmap_config = {
.reg_bits = 32,
.val_bits = 32,
@@ -1275,6 +2088,15 @@ static const struct regmap_config tegra186_ahub_regmap_config = {
.cache_type = REGCACHE_FLAT,
};
+static const struct regmap_config tegra264_ahub_regmap_config = {
+ .reg_bits = 32,
+ .val_bits = 32,
+ .reg_stride = 4,
+ .writeable_reg = tegra264_ahub_wr_reg,
+ .max_register = TEGRA264_MAX_REGISTER_ADDR,
+ .cache_type = REGCACHE_FLAT,
+};
+
static const struct tegra_ahub_soc_data soc_data_tegra210 = {
.cmpnt_drv = &tegra210_ahub_component,
.dai_drv = tegra210_ahub_dais,
@@ -1285,6 +2107,7 @@ static const struct tegra_ahub_soc_data soc_data_tegra210 = {
.mask[2] = TEGRA210_XBAR_REG_MASK_2,
.mask[3] = TEGRA210_XBAR_REG_MASK_3,
.reg_count = TEGRA210_XBAR_UPDATE_MAX_REG,
+ .xbar_part_size = TEGRA210_XBAR_PART1_RX,
};
static const struct tegra_ahub_soc_data soc_data_tegra186 = {
@@ -1297,6 +2120,7 @@ static const struct tegra_ahub_soc_data soc_data_tegra186 = {
.mask[2] = TEGRA186_XBAR_REG_MASK_2,
.mask[3] = TEGRA186_XBAR_REG_MASK_3,
.reg_count = TEGRA186_XBAR_UPDATE_MAX_REG,
+ .xbar_part_size = TEGRA210_XBAR_PART1_RX,
};
static const struct tegra_ahub_soc_data soc_data_tegra234 = {
@@ -1309,17 +2133,33 @@ static const struct tegra_ahub_soc_data soc_data_tegra234 = {
.mask[2] = TEGRA186_XBAR_REG_MASK_2,
.mask[3] = TEGRA186_XBAR_REG_MASK_3,
.reg_count = TEGRA186_XBAR_UPDATE_MAX_REG,
+ .xbar_part_size = TEGRA210_XBAR_PART1_RX,
+};
+
+static const struct tegra_ahub_soc_data soc_data_tegra264 = {
+ .cmpnt_drv = &tegra264_ahub_component,
+ .dai_drv = tegra264_ahub_dais,
+ .num_dais = ARRAY_SIZE(tegra264_ahub_dais),
+ .regmap_config = &tegra264_ahub_regmap_config,
+ .mask[0] = TEGRA264_XBAR_REG_MASK_0,
+ .mask[1] = TEGRA264_XBAR_REG_MASK_1,
+ .mask[2] = TEGRA264_XBAR_REG_MASK_2,
+ .mask[3] = TEGRA264_XBAR_REG_MASK_3,
+ .mask[4] = TEGRA264_XBAR_REG_MASK_4,
+ .reg_count = TEGRA264_XBAR_UPDATE_MAX_REG,
+ .xbar_part_size = TEGRA264_XBAR_PART1_RX,
};
static const struct of_device_id tegra_ahub_of_match[] = {
{ .compatible = "nvidia,tegra210-ahub", .data = &soc_data_tegra210 },
{ .compatible = "nvidia,tegra186-ahub", .data = &soc_data_tegra186 },
{ .compatible = "nvidia,tegra234-ahub", .data = &soc_data_tegra234 },
+ { .compatible = "nvidia,tegra264-ahub", .data = &soc_data_tegra264 },
{},
};
MODULE_DEVICE_TABLE(of, tegra_ahub_of_match);
-static int __maybe_unused tegra_ahub_runtime_suspend(struct device *dev)
+static int tegra_ahub_runtime_suspend(struct device *dev)
{
struct tegra_ahub *ahub = dev_get_drvdata(dev);
@@ -1331,7 +2171,7 @@ static int __maybe_unused tegra_ahub_runtime_suspend(struct device *dev)
return 0;
}
-static int __maybe_unused tegra_ahub_runtime_resume(struct device *dev)
+static int tegra_ahub_runtime_resume(struct device *dev)
{
struct tegra_ahub *ahub = dev_get_drvdata(dev);
int err;
@@ -1359,6 +2199,8 @@ static int tegra_ahub_probe(struct platform_device *pdev)
return -ENOMEM;
ahub->soc_data = of_device_get_match_data(&pdev->dev);
+ if (!ahub->soc_data)
+ return -ENODEV;
platform_set_drvdata(pdev, ahub);
@@ -1391,11 +2233,13 @@ static int tegra_ahub_probe(struct platform_device *pdev)
return err;
}
+ pm_runtime_enable(&pdev->dev);
+
err = of_platform_populate(pdev->dev.of_node, NULL, NULL, &pdev->dev);
- if (err)
+ if (err) {
+ pm_runtime_disable(&pdev->dev);
return err;
-
- pm_runtime_enable(&pdev->dev);
+ }
return 0;
}
@@ -1406,19 +2250,18 @@ static void tegra_ahub_remove(struct platform_device *pdev)
}
static const struct dev_pm_ops tegra_ahub_pm_ops = {
- SET_RUNTIME_PM_OPS(tegra_ahub_runtime_suspend,
- tegra_ahub_runtime_resume, NULL)
- SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
- pm_runtime_force_resume)
+ RUNTIME_PM_OPS(tegra_ahub_runtime_suspend,
+ tegra_ahub_runtime_resume, NULL)
+ SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, pm_runtime_force_resume)
};
static struct platform_driver tegra_ahub_driver = {
.probe = tegra_ahub_probe,
- .remove_new = tegra_ahub_remove,
+ .remove = tegra_ahub_remove,
.driver = {
.name = "tegra210-ahub",
.of_match_table = tegra_ahub_of_match,
- .pm = &tegra_ahub_pm_ops,
+ .pm = pm_ptr(&tegra_ahub_pm_ops),
},
};
module_platform_driver(tegra_ahub_driver);
diff --git a/sound/soc/tegra/tegra210_ahub.h b/sound/soc/tegra/tegra210_ahub.h
index 2728db4d24f2..f355b2cfd19b 100644
--- a/sound/soc/tegra/tegra210_ahub.h
+++ b/sound/soc/tegra/tegra210_ahub.h
@@ -2,7 +2,7 @@
/*
* tegra210_ahub.h - TEGRA210 AHUB
*
- * Copyright (c) 2020-2022, NVIDIA CORPORATION. All rights reserved.
+ * Copyright (c) 2020-2025, NVIDIA CORPORATION. All rights reserved.
*
*/
@@ -28,7 +28,39 @@
#define TEGRA186_XBAR_REG_MASK_3 0x3f0f00ff
#define TEGRA186_XBAR_UPDATE_MAX_REG 4
-#define TEGRA_XBAR_UPDATE_MAX_REG (TEGRA186_XBAR_UPDATE_MAX_REG)
+/* Tegra264 specific */
+#define TEGRA264_XBAR_PART1_RX 0x1000
+#define TEGRA264_XBAR_PART2_RX 0x2000
+#define TEGRA264_XBAR_PART3_RX 0x3000
+#define TEGRA264_XBAR_PART4_RX 0x4000
+#define TEGRA264_XBAR_PART0_ADX6_RX1 0x224
+#define TEGRA264_XBAR_AUDIO_RX_COUNT ((TEGRA264_XBAR_PART0_ADX6_RX1 / 4) + 1)
+#define TEGRA264_XBAR_REG_MASK_0 0xfffffff
+#define TEGRA264_XBAR_REG_MASK_1 0x3f013f1f
+#define TEGRA264_XBAR_REG_MASK_2 0xff3c0301
+#define TEGRA264_XBAR_REG_MASK_3 0x3f00ffff
+#define TEGRA264_XBAR_REG_MASK_4 0x7fff9f
+#define TEGRA264_XBAR_UPDATE_MAX_REG 5
+
+#define TEGRA264_AXBAR_ADMAIF_RX1 0x0
+#define TEGRA264_AXBAR_SFC4_RX1 0x6c
+#define TEGRA264_AXBAR_MIXER1_RX1 0x80
+#define TEGRA264_AXBAR_MIXER1_RX10 0xa4
+#define TEGRA264_AXBAR_DSPK1_RX1 0xc0
+#define TEGRA264_AXBAR_OPE1_RX1 0x100
+#define TEGRA264_AXBAR_MVC1_RX1 0x110
+#define TEGRA264_AXBAR_MVC2_RX1 0x114
+#define TEGRA264_AXBAR_AMX1_RX1 0x120
+#define TEGRA264_AXBAR_AMX3_RX4 0x14c
+#define TEGRA264_AXBAR_ADX1_RX1 0x160
+#define TEGRA264_AXBAR_ASRC1_RX7 0x1a8
+#define TEGRA264_AXBAR_ADMAIF_RX21 0x1d0
+#define TEGRA264_AXBAR_ADX6_RX1 0x224
+
+#define TEGRA_XBAR_UPDATE_MAX_REG (TEGRA264_XBAR_UPDATE_MAX_REG)
+
+#define TEGRA264_MAX_REGISTER_ADDR (TEGRA264_XBAR_PART4_RX + \
+ (TEGRA210_XBAR_RX_STRIDE * (TEGRA264_XBAR_AUDIO_RX_COUNT - 1)))
#define TEGRA186_MAX_REGISTER_ADDR (TEGRA186_XBAR_PART3_RX + \
(TEGRA210_XBAR_RX_STRIDE * (TEGRA186_XBAR_AUDIO_RX_COUNT - 1)))
@@ -76,6 +108,15 @@
#define MUX_ENUM_CTRL_DECL_234(ename, id) MUX_ENUM_CTRL_DECL_186(ename, id)
+#define MUX_ENUM_CTRL_DECL_264(ename, id) \
+ SOC_VALUE_ENUM_WIDE_DECL(ename##_enum, MUX_REG(id), 0, \
+ tegra264_ahub_mux_texts, \
+ tegra264_ahub_mux_values); \
+ static const struct snd_kcontrol_new ename##_control = \
+ SOC_DAPM_ENUM_EXT("Route", ename##_enum, \
+ tegra_ahub_get_value_enum, \
+ tegra_ahub_put_value_enum)
+
#define WIDGETS(sname, ename) \
SND_SOC_DAPM_AIF_IN(sname " XBAR-RX", NULL, 0, SND_SOC_NOPM, 0, 0), \
SND_SOC_DAPM_AIF_OUT(sname " XBAR-TX", NULL, 0, SND_SOC_NOPM, 0, 0), \
@@ -92,7 +133,7 @@
.playback = { \
.stream_name = #sname " XBAR-Playback", \
.channels_min = 1, \
- .channels_max = 16, \
+ .channels_max = 32, \
.rates = SNDRV_PCM_RATE_8000_192000, \
.formats = SNDRV_PCM_FMTBIT_S8 | \
SNDRV_PCM_FMTBIT_S16_LE | \
@@ -102,7 +143,7 @@
.capture = { \
.stream_name = #sname " XBAR-Capture", \
.channels_min = 1, \
- .channels_max = 16, \
+ .channels_max = 32, \
.rates = SNDRV_PCM_RATE_8000_192000, \
.formats = SNDRV_PCM_FMTBIT_S8 | \
SNDRV_PCM_FMTBIT_S16_LE | \
@@ -115,9 +156,10 @@ struct tegra_ahub_soc_data {
const struct regmap_config *regmap_config;
const struct snd_soc_component_driver *cmpnt_drv;
struct snd_soc_dai_driver *dai_drv;
- unsigned int mask[4];
+ unsigned int mask[TEGRA_XBAR_UPDATE_MAX_REG];
unsigned int reg_count;
unsigned int num_dais;
+ unsigned int xbar_part_size;
};
struct tegra_ahub {
diff --git a/sound/soc/tegra/tegra210_amx.c b/sound/soc/tegra/tegra210_amx.c
index 91e405909e0f..7f558c40e097 100644
--- a/sound/soc/tegra/tegra210_amx.c
+++ b/sound/soc/tegra/tegra210_amx.c
@@ -1,8 +1,8 @@
// SPDX-License-Identifier: GPL-2.0-only
+// SPDX-FileCopyrightText: Copyright (c) 2021-2025 NVIDIA CORPORATION & AFFILIATES.
+// All rights reserved.
//
// tegra210_amx.c - Tegra210 AMX driver
-//
-// Copyright (c) 2021-2023 NVIDIA CORPORATION. All rights reserved.
#include <linux/clk.h>
#include <linux/device.h>
@@ -46,21 +46,35 @@ static const struct reg_default tegra210_amx_reg_defaults[] = {
{ TEGRA210_AMX_CFG_RAM_CTRL, 0x00004000},
};
+static const struct reg_default tegra264_amx_reg_defaults[] = {
+ { TEGRA210_AMX_RX_INT_MASK, 0x0000000f},
+ { TEGRA210_AMX_RX1_CIF_CTRL, 0x00003800},
+ { TEGRA210_AMX_RX2_CIF_CTRL, 0x00003800},
+ { TEGRA210_AMX_RX3_CIF_CTRL, 0x00003800},
+ { TEGRA210_AMX_RX4_CIF_CTRL, 0x00003800},
+ { TEGRA210_AMX_TX_INT_MASK, 0x00000001},
+ { TEGRA210_AMX_TX_CIF_CTRL, 0x00003800},
+ { TEGRA210_AMX_CG, 0x1},
+ { TEGRA264_AMX_CFG_RAM_CTRL, 0x00004000},
+};
+
static void tegra210_amx_write_map_ram(struct tegra210_amx *amx)
{
int i;
- regmap_write(amx->regmap, TEGRA210_AMX_CFG_RAM_CTRL,
+ regmap_write(amx->regmap, TEGRA210_AMX_CFG_RAM_CTRL + amx->soc_data->reg_offset,
TEGRA210_AMX_CFG_RAM_CTRL_SEQ_ACCESS_EN |
TEGRA210_AMX_CFG_RAM_CTRL_ADDR_INIT_EN |
TEGRA210_AMX_CFG_RAM_CTRL_RW_WRITE);
- for (i = 0; i < TEGRA210_AMX_RAM_DEPTH; i++)
- regmap_write(amx->regmap, TEGRA210_AMX_CFG_RAM_DATA,
+ for (i = 0; i < amx->soc_data->ram_depth; i++)
+ regmap_write(amx->regmap, TEGRA210_AMX_CFG_RAM_DATA + amx->soc_data->reg_offset,
amx->map[i]);
- regmap_write(amx->regmap, TEGRA210_AMX_OUT_BYTE_EN0, amx->byte_mask[0]);
- regmap_write(amx->regmap, TEGRA210_AMX_OUT_BYTE_EN1, amx->byte_mask[1]);
+ for (i = 0; i < amx->soc_data->byte_mask_size; i++)
+ regmap_write(amx->regmap,
+ TEGRA210_AMX_OUT_BYTE_EN0 + (i * TEGRA210_AMX_AUDIOCIF_CH_STRIDE),
+ amx->byte_mask[i]);
}
static int tegra210_amx_startup(struct snd_pcm_substream *substream,
@@ -98,7 +112,7 @@ static int tegra210_amx_startup(struct snd_pcm_substream *substream,
return 0;
}
-static int __maybe_unused tegra210_amx_runtime_suspend(struct device *dev)
+static int tegra210_amx_runtime_suspend(struct device *dev)
{
struct tegra210_amx *amx = dev_get_drvdata(dev);
@@ -108,7 +122,7 @@ static int __maybe_unused tegra210_amx_runtime_suspend(struct device *dev)
return 0;
}
-static int __maybe_unused tegra210_amx_runtime_resume(struct device *dev)
+static int tegra210_amx_runtime_resume(struct device *dev)
{
struct tegra210_amx *amx = dev_get_drvdata(dev);
@@ -144,6 +158,7 @@ static int tegra210_amx_set_audio_cif(struct snd_soc_dai *dai,
case SNDRV_PCM_FORMAT_S16_LE:
audio_bits = TEGRA_ACIF_BITS_16;
break;
+ case SNDRV_PCM_FORMAT_S24_LE:
case SNDRV_PCM_FORMAT_S32_LE:
audio_bits = TEGRA_ACIF_BITS_32;
break;
@@ -156,7 +171,10 @@ static int tegra210_amx_set_audio_cif(struct snd_soc_dai *dai,
cif_conf.audio_bits = audio_bits;
cif_conf.client_bits = audio_bits;
- tegra_set_cif(amx->regmap, reg, &cif_conf);
+ if (amx->soc_data->max_ch == TEGRA264_AMX_MAX_CHANNEL)
+ tegra264_set_cif(amx->regmap, reg, &cif_conf);
+ else
+ tegra_set_cif(amx->regmap, reg, &cif_conf);
return 0;
}
@@ -169,9 +187,10 @@ static int tegra210_amx_in_hw_params(struct snd_pcm_substream *substream,
if (amx->soc_data->auto_disable) {
regmap_write(amx->regmap,
- AMX_CH_REG(dai->id, TEGRA194_AMX_RX1_FRAME_PERIOD),
+ AMX_CH_REG(dai->id, TEGRA194_AMX_RX1_FRAME_PERIOD +
+ amx->soc_data->reg_offset),
TEGRA194_MAX_FRAME_IDLE_COUNT);
- regmap_write(amx->regmap, TEGRA210_AMX_CYA, 1);
+ regmap_write(amx->regmap, TEGRA210_AMX_CYA + amx->soc_data->reg_offset, 1);
}
return tegra210_amx_set_audio_cif(dai, params,
@@ -193,14 +212,11 @@ static int tegra210_amx_get_byte_map(struct snd_kcontrol *kcontrol,
struct soc_mixer_control *mc =
(struct soc_mixer_control *)kcontrol->private_value;
struct tegra210_amx *amx = snd_soc_component_get_drvdata(cmpnt);
- unsigned char *bytes_map = (unsigned char *)&amx->map;
+ unsigned char *bytes_map = (unsigned char *)amx->map;
int reg = mc->reg;
int enabled;
- if (reg > 31)
- enabled = amx->byte_mask[1] & (1 << (reg - 32));
- else
- enabled = amx->byte_mask[0] & (1 << reg);
+ enabled = amx->byte_mask[reg / 32] & (1 << (reg % 32));
/*
* TODO: Simplify this logic to just return from bytes_map[]
@@ -227,7 +243,7 @@ static int tegra210_amx_put_byte_map(struct snd_kcontrol *kcontrol,
(struct soc_mixer_control *)kcontrol->private_value;
struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
struct tegra210_amx *amx = snd_soc_component_get_drvdata(cmpnt);
- unsigned char *bytes_map = (unsigned char *)&amx->map;
+ unsigned char *bytes_map = (unsigned char *)amx->map;
int reg = mc->reg;
int value = ucontrol->value.integer.value[0];
unsigned int mask_val = amx->byte_mask[reg / 32];
@@ -266,6 +282,7 @@ static const struct snd_soc_dai_ops tegra210_amx_in_dai_ops = {
.rates = SNDRV_PCM_RATE_8000_192000, \
.formats = SNDRV_PCM_FMTBIT_S8 | \
SNDRV_PCM_FMTBIT_S16_LE | \
+ SNDRV_PCM_FMTBIT_S24_LE | \
SNDRV_PCM_FMTBIT_S32_LE, \
}, \
.capture = { \
@@ -275,6 +292,7 @@ static const struct snd_soc_dai_ops tegra210_amx_in_dai_ops = {
.rates = SNDRV_PCM_RATE_8000_192000, \
.formats = SNDRV_PCM_FMTBIT_S8 | \
SNDRV_PCM_FMTBIT_S16_LE | \
+ SNDRV_PCM_FMTBIT_S24_LE | \
SNDRV_PCM_FMTBIT_S32_LE, \
}, \
.ops = &tegra210_amx_in_dai_ops, \
@@ -290,6 +308,7 @@ static const struct snd_soc_dai_ops tegra210_amx_in_dai_ops = {
.rates = SNDRV_PCM_RATE_8000_192000, \
.formats = SNDRV_PCM_FMTBIT_S8 | \
SNDRV_PCM_FMTBIT_S16_LE | \
+ SNDRV_PCM_FMTBIT_S24_LE | \
SNDRV_PCM_FMTBIT_S32_LE, \
}, \
.capture = { \
@@ -299,6 +318,7 @@ static const struct snd_soc_dai_ops tegra210_amx_in_dai_ops = {
.rates = SNDRV_PCM_RATE_8000_192000, \
.formats = SNDRV_PCM_FMTBIT_S8 | \
SNDRV_PCM_FMTBIT_S16_LE | \
+ SNDRV_PCM_FMTBIT_S24_LE | \
SNDRV_PCM_FMTBIT_S32_LE, \
}, \
.ops = &tegra210_amx_out_dai_ops, \
@@ -413,7 +433,90 @@ static struct snd_kcontrol_new tegra210_amx_controls[] = {
TEGRA210_AMX_BYTE_MAP_CTRL(63),
};
+static struct snd_kcontrol_new tegra264_amx_controls[] = {
+ TEGRA210_AMX_BYTE_MAP_CTRL(64),
+ TEGRA210_AMX_BYTE_MAP_CTRL(65),
+ TEGRA210_AMX_BYTE_MAP_CTRL(66),
+ TEGRA210_AMX_BYTE_MAP_CTRL(67),
+ TEGRA210_AMX_BYTE_MAP_CTRL(68),
+ TEGRA210_AMX_BYTE_MAP_CTRL(69),
+ TEGRA210_AMX_BYTE_MAP_CTRL(70),
+ TEGRA210_AMX_BYTE_MAP_CTRL(71),
+ TEGRA210_AMX_BYTE_MAP_CTRL(72),
+ TEGRA210_AMX_BYTE_MAP_CTRL(73),
+ TEGRA210_AMX_BYTE_MAP_CTRL(74),
+ TEGRA210_AMX_BYTE_MAP_CTRL(75),
+ TEGRA210_AMX_BYTE_MAP_CTRL(76),
+ TEGRA210_AMX_BYTE_MAP_CTRL(77),
+ TEGRA210_AMX_BYTE_MAP_CTRL(78),
+ TEGRA210_AMX_BYTE_MAP_CTRL(79),
+ TEGRA210_AMX_BYTE_MAP_CTRL(80),
+ TEGRA210_AMX_BYTE_MAP_CTRL(81),
+ TEGRA210_AMX_BYTE_MAP_CTRL(82),
+ TEGRA210_AMX_BYTE_MAP_CTRL(83),
+ TEGRA210_AMX_BYTE_MAP_CTRL(84),
+ TEGRA210_AMX_BYTE_MAP_CTRL(85),
+ TEGRA210_AMX_BYTE_MAP_CTRL(86),
+ TEGRA210_AMX_BYTE_MAP_CTRL(87),
+ TEGRA210_AMX_BYTE_MAP_CTRL(88),
+ TEGRA210_AMX_BYTE_MAP_CTRL(89),
+ TEGRA210_AMX_BYTE_MAP_CTRL(90),
+ TEGRA210_AMX_BYTE_MAP_CTRL(91),
+ TEGRA210_AMX_BYTE_MAP_CTRL(92),
+ TEGRA210_AMX_BYTE_MAP_CTRL(93),
+ TEGRA210_AMX_BYTE_MAP_CTRL(94),
+ TEGRA210_AMX_BYTE_MAP_CTRL(95),
+ TEGRA210_AMX_BYTE_MAP_CTRL(96),
+ TEGRA210_AMX_BYTE_MAP_CTRL(97),
+ TEGRA210_AMX_BYTE_MAP_CTRL(98),
+ TEGRA210_AMX_BYTE_MAP_CTRL(99),
+ TEGRA210_AMX_BYTE_MAP_CTRL(100),
+ TEGRA210_AMX_BYTE_MAP_CTRL(101),
+ TEGRA210_AMX_BYTE_MAP_CTRL(102),
+ TEGRA210_AMX_BYTE_MAP_CTRL(103),
+ TEGRA210_AMX_BYTE_MAP_CTRL(104),
+ TEGRA210_AMX_BYTE_MAP_CTRL(105),
+ TEGRA210_AMX_BYTE_MAP_CTRL(106),
+ TEGRA210_AMX_BYTE_MAP_CTRL(107),
+ TEGRA210_AMX_BYTE_MAP_CTRL(108),
+ TEGRA210_AMX_BYTE_MAP_CTRL(109),
+ TEGRA210_AMX_BYTE_MAP_CTRL(110),
+ TEGRA210_AMX_BYTE_MAP_CTRL(111),
+ TEGRA210_AMX_BYTE_MAP_CTRL(112),
+ TEGRA210_AMX_BYTE_MAP_CTRL(113),
+ TEGRA210_AMX_BYTE_MAP_CTRL(114),
+ TEGRA210_AMX_BYTE_MAP_CTRL(115),
+ TEGRA210_AMX_BYTE_MAP_CTRL(116),
+ TEGRA210_AMX_BYTE_MAP_CTRL(117),
+ TEGRA210_AMX_BYTE_MAP_CTRL(118),
+ TEGRA210_AMX_BYTE_MAP_CTRL(119),
+ TEGRA210_AMX_BYTE_MAP_CTRL(120),
+ TEGRA210_AMX_BYTE_MAP_CTRL(121),
+ TEGRA210_AMX_BYTE_MAP_CTRL(122),
+ TEGRA210_AMX_BYTE_MAP_CTRL(123),
+ TEGRA210_AMX_BYTE_MAP_CTRL(124),
+ TEGRA210_AMX_BYTE_MAP_CTRL(125),
+ TEGRA210_AMX_BYTE_MAP_CTRL(126),
+ TEGRA210_AMX_BYTE_MAP_CTRL(127),
+};
+
+static int tegra210_amx_component_probe(struct snd_soc_component *component)
+{
+ struct tegra210_amx *amx = snd_soc_component_get_drvdata(component);
+ int err = 0;
+
+ if (amx->soc_data->num_controls) {
+ err = snd_soc_add_component_controls(component, amx->soc_data->controls,
+ amx->soc_data->num_controls);
+ if (err)
+ dev_err(component->dev, "can't add AMX controls, err: %d\n", err);
+ }
+
+ return err;
+}
+
static const struct snd_soc_component_driver tegra210_amx_cmpnt = {
+ .probe = tegra210_amx_component_probe,
.dapm_widgets = tegra210_amx_widgets,
.num_dapm_widgets = ARRAY_SIZE(tegra210_amx_widgets),
.dapm_routes = tegra210_amx_routes,
@@ -445,6 +548,22 @@ static bool tegra194_amx_wr_reg(struct device *dev, unsigned int reg)
}
}
+static bool tegra264_amx_wr_reg(struct device *dev,
+ unsigned int reg)
+{
+ switch (reg) {
+ case TEGRA210_AMX_RX_INT_MASK ... TEGRA210_AMX_RX4_CIF_CTRL:
+ case TEGRA210_AMX_TX_INT_MASK ... TEGRA210_AMX_TX_CIF_CTRL:
+ case TEGRA210_AMX_ENABLE ... TEGRA210_AMX_CG:
+ case TEGRA210_AMX_CTRL ... TEGRA264_AMX_STREAMS_AUTO_DISABLE:
+ case TEGRA264_AMX_CFG_RAM_CTRL ... TEGRA264_AMX_CFG_RAM_DATA:
+ case TEGRA264_AMX_RX1_FRAME_PERIOD ... TEGRA264_AMX_RX4_FRAME_PERIOD:
+ return true;
+ default:
+ return false;
+ }
+}
+
static bool tegra210_amx_rd_reg(struct device *dev, unsigned int reg)
{
switch (reg) {
@@ -465,6 +584,21 @@ static bool tegra194_amx_rd_reg(struct device *dev, unsigned int reg)
}
}
+static bool tegra264_amx_rd_reg(struct device *dev,
+ unsigned int reg)
+{
+ switch (reg) {
+ case TEGRA210_AMX_RX_STATUS ... TEGRA210_AMX_RX4_CIF_CTRL:
+ case TEGRA210_AMX_TX_STATUS ... TEGRA210_AMX_TX_CIF_CTRL:
+ case TEGRA210_AMX_ENABLE ... TEGRA210_AMX_INT_STATUS:
+ case TEGRA210_AMX_CTRL ... TEGRA264_AMX_CFG_RAM_DATA:
+ case TEGRA264_AMX_RX1_FRAME_PERIOD ... TEGRA264_AMX_RX4_FRAME_PERIOD:
+ return true;
+ default:
+ return false;
+ }
+}
+
static bool tegra210_amx_volatile_reg(struct device *dev, unsigned int reg)
{
switch (reg) {
@@ -487,6 +621,29 @@ static bool tegra210_amx_volatile_reg(struct device *dev, unsigned int reg)
return false;
}
+static bool tegra264_amx_volatile_reg(struct device *dev,
+ unsigned int reg)
+{
+ switch (reg) {
+ case TEGRA210_AMX_RX_STATUS:
+ case TEGRA210_AMX_RX_INT_STATUS:
+ case TEGRA210_AMX_RX_INT_SET:
+ case TEGRA210_AMX_TX_STATUS:
+ case TEGRA210_AMX_TX_INT_STATUS:
+ case TEGRA210_AMX_TX_INT_SET:
+ case TEGRA210_AMX_SOFT_RESET:
+ case TEGRA210_AMX_STATUS:
+ case TEGRA210_AMX_INT_STATUS:
+ case TEGRA264_AMX_CFG_RAM_CTRL:
+ case TEGRA264_AMX_CFG_RAM_DATA:
+ return true;
+ default:
+ break;
+ }
+
+ return false;
+}
+
static const struct regmap_config tegra210_amx_regmap_config = {
.reg_bits = 32,
.reg_stride = 4,
@@ -513,18 +670,51 @@ static const struct regmap_config tegra194_amx_regmap_config = {
.cache_type = REGCACHE_FLAT,
};
+static const struct regmap_config tegra264_amx_regmap_config = {
+ .reg_bits = 32,
+ .reg_stride = 4,
+ .val_bits = 32,
+ .max_register = TEGRA264_AMX_RX4_LAST_FRAME_PERIOD,
+ .writeable_reg = tegra264_amx_wr_reg,
+ .readable_reg = tegra264_amx_rd_reg,
+ .volatile_reg = tegra264_amx_volatile_reg,
+ .reg_defaults = tegra264_amx_reg_defaults,
+ .num_reg_defaults = ARRAY_SIZE(tegra264_amx_reg_defaults),
+ .cache_type = REGCACHE_FLAT,
+};
+
static const struct tegra210_amx_soc_data soc_data_tegra210 = {
.regmap_conf = &tegra210_amx_regmap_config,
+ .max_ch = TEGRA210_AMX_MAX_CHANNEL,
+ .ram_depth = TEGRA210_AMX_RAM_DEPTH,
+ .byte_mask_size = TEGRA210_AMX_BYTE_MASK_COUNT,
+ .reg_offset = TEGRA210_AMX_AUTO_DISABLE_OFFSET,
};
static const struct tegra210_amx_soc_data soc_data_tegra194 = {
.regmap_conf = &tegra194_amx_regmap_config,
.auto_disable = true,
+ .max_ch = TEGRA210_AMX_MAX_CHANNEL,
+ .ram_depth = TEGRA210_AMX_RAM_DEPTH,
+ .byte_mask_size = TEGRA210_AMX_BYTE_MASK_COUNT,
+ .reg_offset = TEGRA210_AMX_AUTO_DISABLE_OFFSET,
+};
+
+static const struct tegra210_amx_soc_data soc_data_tegra264 = {
+ .regmap_conf = &tegra264_amx_regmap_config,
+ .auto_disable = true,
+ .max_ch = TEGRA264_AMX_MAX_CHANNEL,
+ .ram_depth = TEGRA264_AMX_RAM_DEPTH,
+ .byte_mask_size = TEGRA264_AMX_BYTE_MASK_COUNT,
+ .reg_offset = TEGRA264_AMX_AUTO_DISABLE_OFFSET,
+ .controls = tegra264_amx_controls,
+ .num_controls = ARRAY_SIZE(tegra264_amx_controls),
};
static const struct of_device_id tegra210_amx_of_match[] = {
{ .compatible = "nvidia,tegra210-amx", .data = &soc_data_tegra210 },
{ .compatible = "nvidia,tegra194-amx", .data = &soc_data_tegra194 },
+ { .compatible = "nvidia,tegra264-amx", .data = &soc_data_tegra264 },
{},
};
MODULE_DEVICE_TABLE(of, tegra210_amx_of_match);
@@ -557,6 +747,20 @@ static int tegra210_amx_platform_probe(struct platform_device *pdev)
regcache_cache_only(amx->regmap, true);
+ amx->map = devm_kzalloc(dev, amx->soc_data->ram_depth * sizeof(*amx->map),
+ GFP_KERNEL);
+ if (!amx->map)
+ return -ENOMEM;
+
+ amx->byte_mask = devm_kzalloc(dev,
+ amx->soc_data->byte_mask_size * sizeof(*amx->byte_mask),
+ GFP_KERNEL);
+ if (!amx->byte_mask)
+ return -ENOMEM;
+
+ tegra210_amx_dais[TEGRA_AMX_OUT_DAI_ID].capture.channels_max =
+ amx->soc_data->max_ch;
+
err = devm_snd_soc_register_component(dev, &tegra210_amx_cmpnt,
tegra210_amx_dais,
ARRAY_SIZE(tegra210_amx_dais));
@@ -576,20 +780,19 @@ static void tegra210_amx_platform_remove(struct platform_device *pdev)
}
static const struct dev_pm_ops tegra210_amx_pm_ops = {
- SET_RUNTIME_PM_OPS(tegra210_amx_runtime_suspend,
- tegra210_amx_runtime_resume, NULL)
- SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
- pm_runtime_force_resume)
+ RUNTIME_PM_OPS(tegra210_amx_runtime_suspend,
+ tegra210_amx_runtime_resume, NULL)
+ SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, pm_runtime_force_resume)
};
static struct platform_driver tegra210_amx_driver = {
.driver = {
.name = "tegra210-amx",
.of_match_table = tegra210_amx_of_match,
- .pm = &tegra210_amx_pm_ops,
+ .pm = pm_ptr(&tegra210_amx_pm_ops),
},
.probe = tegra210_amx_platform_probe,
- .remove_new = tegra210_amx_platform_remove,
+ .remove = tegra210_amx_platform_remove,
};
module_platform_driver(tegra210_amx_driver);
diff --git a/sound/soc/tegra/tegra210_amx.h b/sound/soc/tegra/tegra210_amx.h
index e277741e4258..50a237b197ba 100644
--- a/sound/soc/tegra/tegra210_amx.h
+++ b/sound/soc/tegra/tegra210_amx.h
@@ -1,8 +1,7 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * tegra210_amx.h - Definitions for Tegra210 AMX driver
+/* SPDX-License-Identifier: GPL-2.0-only
+ * SPDX-FileCopyrightText: Copyright (c) 2021-2025 NVIDIA CORPORATION. All rights reserved.
*
- * Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved.
+ * tegra210_amx.h - Definitions for Tegra210 AMX driver
*
*/
@@ -32,7 +31,6 @@
#define TEGRA210_AMX_INT_STATUS 0x90
#define TEGRA210_AMX_CTRL 0xa4
#define TEGRA210_AMX_OUT_BYTE_EN0 0xa8
-#define TEGRA210_AMX_OUT_BYTE_EN1 0xac
#define TEGRA210_AMX_CYA 0xb0
#define TEGRA210_AMX_CFG_RAM_CTRL 0xb8
#define TEGRA210_AMX_CFG_RAM_DATA 0xbc
@@ -41,6 +39,13 @@
#define TEGRA194_AMX_RX4_FRAME_PERIOD 0xcc
#define TEGRA194_AMX_RX4_LAST_FRAME_PERIOD 0xdc
+#define TEGRA264_AMX_STREAMS_AUTO_DISABLE 0xb8
+#define TEGRA264_AMX_CFG_RAM_CTRL 0xc0
+#define TEGRA264_AMX_CFG_RAM_DATA 0xc4
+#define TEGRA264_AMX_RX1_FRAME_PERIOD 0xc8
+#define TEGRA264_AMX_RX4_FRAME_PERIOD 0xd4
+#define TEGRA264_AMX_RX4_LAST_FRAME_PERIOD 0xe4
+
/* Fields in TEGRA210_AMX_ENABLE */
#define TEGRA210_AMX_ENABLE_SHIFT 0
@@ -72,6 +77,15 @@
#define TEGRA210_AMX_MAP_STREAM_NUM_SHIFT 6
#define TEGRA210_AMX_MAP_WORD_NUM_SHIFT 2
#define TEGRA210_AMX_MAP_BYTE_NUM_SHIFT 0
+#define TEGRA210_AMX_BYTE_MASK_COUNT 2
+#define TEGRA210_AMX_MAX_CHANNEL 16
+#define TEGRA210_AMX_AUTO_DISABLE_OFFSET 0
+
+#define TEGRA264_AMX_RAM_DEPTH 32
+#define TEGRA264_AMX_BYTE_MASK_COUNT 4
+#define TEGRA264_AMX_MAX_CHANNEL 32
+#define TEGRA264_AMX_AUTO_DISABLE_OFFSET 8
+#define TEGRA_AMX_OUT_DAI_ID 4
enum {
TEGRA210_AMX_WAIT_ON_ALL,
@@ -81,13 +95,19 @@ enum {
struct tegra210_amx_soc_data {
const struct regmap_config *regmap_conf;
bool auto_disable;
+ const struct snd_kcontrol_new *controls;
+ unsigned int num_controls;
+ unsigned int max_ch;
+ unsigned int ram_depth;
+ unsigned int byte_mask_size;
+ unsigned int reg_offset;
};
struct tegra210_amx {
const struct tegra210_amx_soc_data *soc_data;
- unsigned int map[TEGRA210_AMX_RAM_DEPTH];
+ unsigned int *map;
+ unsigned int *byte_mask;
struct regmap *regmap;
- unsigned int byte_mask[2];
};
#endif
diff --git a/sound/soc/tegra/tegra210_dmic.c b/sound/soc/tegra/tegra210_dmic.c
index e53c0278ae9a..e4a144571265 100644
--- a/sound/soc/tegra/tegra210_dmic.c
+++ b/sound/soc/tegra/tegra210_dmic.c
@@ -1,8 +1,8 @@
// SPDX-License-Identifier: GPL-2.0-only
+// SPDX-FileCopyrightText: Copyright (c) 2020-2024 NVIDIA CORPORATION & AFFILIATES.
+// All rights reserved.
//
// tegra210_dmic.c - Tegra210 DMIC driver
-//
-// Copyright (c) 2020 NVIDIA CORPORATION. All rights reserved.
#include <linux/clk.h>
#include <linux/device.h>
@@ -40,7 +40,7 @@ static const struct reg_default tegra210_dmic_reg_defaults[] = {
{ TEGRA210_DMIC_LP_BIQUAD_1_COEF_4, 0x0 },
};
-static int __maybe_unused tegra210_dmic_runtime_suspend(struct device *dev)
+static int tegra210_dmic_runtime_suspend(struct device *dev)
{
struct tegra210_dmic *dmic = dev_get_drvdata(dev);
@@ -52,7 +52,7 @@ static int __maybe_unused tegra210_dmic_runtime_suspend(struct device *dev)
return 0;
}
-static int __maybe_unused tegra210_dmic_runtime_resume(struct device *dev)
+static int tegra210_dmic_runtime_resume(struct device *dev)
{
struct tegra210_dmic *dmic = dev_get_drvdata(dev);
int err;
@@ -139,6 +139,7 @@ static int tegra210_dmic_hw_params(struct snd_pcm_substream *substream,
case SNDRV_PCM_FORMAT_S16_LE:
cif_conf.audio_bits = TEGRA_ACIF_BITS_16;
break;
+ case SNDRV_PCM_FORMAT_S24_LE:
case SNDRV_PCM_FORMAT_S32_LE:
cif_conf.audio_bits = TEGRA_ACIF_BITS_32;
break;
@@ -325,6 +326,7 @@ static struct snd_soc_dai_driver tegra210_dmic_dais[] = {
.channels_max = 2,
.rates = SNDRV_PCM_RATE_8000_48000,
.formats = SNDRV_PCM_FMTBIT_S16_LE |
+ SNDRV_PCM_FMTBIT_S24_LE |
SNDRV_PCM_FMTBIT_S32_LE,
},
},
@@ -336,6 +338,7 @@ static struct snd_soc_dai_driver tegra210_dmic_dais[] = {
.channels_max = 2,
.rates = SNDRV_PCM_RATE_8000_48000,
.formats = SNDRV_PCM_FMTBIT_S16_LE |
+ SNDRV_PCM_FMTBIT_S24_LE |
SNDRV_PCM_FMTBIT_S32_LE,
},
.ops = &tegra210_dmic_dai_ops,
@@ -540,10 +543,9 @@ static void tegra210_dmic_remove(struct platform_device *pdev)
}
static const struct dev_pm_ops tegra210_dmic_pm_ops = {
- SET_RUNTIME_PM_OPS(tegra210_dmic_runtime_suspend,
- tegra210_dmic_runtime_resume, NULL)
- SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
- pm_runtime_force_resume)
+ RUNTIME_PM_OPS(tegra210_dmic_runtime_suspend,
+ tegra210_dmic_runtime_resume, NULL)
+ SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, pm_runtime_force_resume)
};
static const struct of_device_id tegra210_dmic_of_match[] = {
@@ -556,10 +558,10 @@ static struct platform_driver tegra210_dmic_driver = {
.driver = {
.name = "tegra210-dmic",
.of_match_table = tegra210_dmic_of_match,
- .pm = &tegra210_dmic_pm_ops,
+ .pm = pm_ptr(&tegra210_dmic_pm_ops),
},
.probe = tegra210_dmic_probe,
- .remove_new = tegra210_dmic_remove,
+ .remove = tegra210_dmic_remove,
};
module_platform_driver(tegra210_dmic_driver)
diff --git a/sound/soc/tegra/tegra210_i2s.c b/sound/soc/tegra/tegra210_i2s.c
index ba7fdd7405ac..100277c39001 100644
--- a/sound/soc/tegra/tegra210_i2s.c
+++ b/sound/soc/tegra/tegra210_i2s.c
@@ -1,18 +1,20 @@
// SPDX-License-Identifier: GPL-2.0-only
+// SPDX-FileCopyrightText: Copyright (c) 2020-2025 NVIDIA CORPORATION & AFFILIATES.
+// All rights reserved.
//
// tegra210_i2s.c - Tegra210 I2S driver
-//
-// Copyright (c) 2020 NVIDIA CORPORATION. All rights reserved.
#include <linux/clk.h>
#include <linux/device.h>
#include <linux/mod_devicetable.h>
#include <linux/module.h>
+#include <linux/of_graph.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/regmap.h>
#include <sound/core.h>
#include <sound/pcm_params.h>
+#include <sound/simple_card_utils.h>
#include <sound/soc.h>
#include "tegra210_i2s.h"
#include "tegra_cif.h"
@@ -34,14 +36,28 @@ static const struct reg_default tegra210_i2s_reg_defaults[] = {
{ TEGRA210_I2S_CYA, 0x1 },
};
-static void tegra210_i2s_set_slot_ctrl(struct regmap *regmap,
+static const struct reg_default tegra264_i2s_reg_defaults[] = {
+ { TEGRA210_I2S_RX_INT_MASK, 0x00000003 },
+ { TEGRA210_I2S_RX_CIF_CTRL, 0x00003f00 },
+ { TEGRA264_I2S_TX_INT_MASK, 0x00000003 },
+ { TEGRA264_I2S_TX_CIF_CTRL, 0x00003f00 },
+ { TEGRA264_I2S_CG, 0x1 },
+ { TEGRA264_I2S_TIMING, 0x0000001f },
+ { TEGRA264_I2S_ENABLE, 0x1 },
+ { TEGRA264_I2S_RX_FIFO_WR_ACCESS_MODE, 0x1 },
+ { TEGRA264_I2S_TX_FIFO_RD_ACCESS_MODE, 0x1 },
+};
+
+static void tegra210_i2s_set_slot_ctrl(struct tegra210_i2s *i2s,
unsigned int total_slots,
unsigned int tx_slot_mask,
unsigned int rx_slot_mask)
{
- regmap_write(regmap, TEGRA210_I2S_SLOT_CTRL, total_slots - 1);
- regmap_write(regmap, TEGRA210_I2S_TX_SLOT_CTRL, tx_slot_mask);
- regmap_write(regmap, TEGRA210_I2S_RX_SLOT_CTRL, rx_slot_mask);
+ regmap_write(i2s->regmap, TEGRA210_I2S_SLOT_CTRL + i2s->soc_data->i2s_ctrl_offset,
+ total_slots - 1);
+ regmap_write(i2s->regmap, TEGRA210_I2S_TX_SLOT_CTRL + i2s->soc_data->tx_offset,
+ tx_slot_mask);
+ regmap_write(i2s->regmap, TEGRA210_I2S_RX_SLOT_CTRL, rx_slot_mask);
}
static int tegra210_i2s_set_clock_rate(struct device *dev,
@@ -51,7 +67,7 @@ static int tegra210_i2s_set_clock_rate(struct device *dev,
unsigned int val;
int err;
- regmap_read(i2s->regmap, TEGRA210_I2S_CTRL, &val);
+ regmap_read(i2s->regmap, TEGRA210_I2S_CTRL + i2s->soc_data->i2s_ctrl_offset, &val);
/* No need to set rates if I2S is being operated in slave */
if (!(val & I2S_CTRL_MASTER_EN))
@@ -83,7 +99,7 @@ static int tegra210_i2s_set_clock_rate(struct device *dev,
}
static int tegra210_i2s_sw_reset(struct snd_soc_component *compnt,
- bool is_playback)
+ int stream)
{
struct device *dev = compnt->dev;
struct tegra210_i2s *i2s = dev_get_drvdata(dev);
@@ -93,20 +109,20 @@ static int tegra210_i2s_sw_reset(struct snd_soc_component *compnt,
unsigned int cif_ctrl, stream_ctrl, i2s_ctrl, val;
int err;
- if (is_playback) {
+ if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
reset_reg = TEGRA210_I2S_RX_SOFT_RESET;
cif_reg = TEGRA210_I2S_RX_CIF_CTRL;
stream_reg = TEGRA210_I2S_RX_CTRL;
} else {
- reset_reg = TEGRA210_I2S_TX_SOFT_RESET;
- cif_reg = TEGRA210_I2S_TX_CIF_CTRL;
- stream_reg = TEGRA210_I2S_TX_CTRL;
+ reset_reg = TEGRA210_I2S_TX_SOFT_RESET + i2s->soc_data->tx_offset;
+ cif_reg = TEGRA210_I2S_TX_CIF_CTRL + i2s->soc_data->tx_offset;
+ stream_reg = TEGRA210_I2S_TX_CTRL + i2s->soc_data->tx_offset;
}
/* Store CIF and I2S control values */
regmap_read(i2s->regmap, cif_reg, &cif_ctrl);
regmap_read(i2s->regmap, stream_reg, &stream_ctrl);
- regmap_read(i2s->regmap, TEGRA210_I2S_CTRL, &i2s_ctrl);
+ regmap_read(i2s->regmap, TEGRA210_I2S_CTRL + i2s->soc_data->i2s_ctrl_offset, &i2s_ctrl);
/* Reset to make sure the previous transactions are clean */
regmap_update_bits(i2s->regmap, reset_reg, reset_mask, reset_en);
@@ -116,14 +132,14 @@ static int tegra210_i2s_sw_reset(struct snd_soc_component *compnt,
10, 10000);
if (err) {
dev_err(dev, "timeout: failed to reset I2S for %s\n",
- is_playback ? "playback" : "capture");
+ snd_pcm_direction_name(stream));
return err;
}
/* Restore CIF and I2S control values */
regmap_write(i2s->regmap, cif_reg, cif_ctrl);
regmap_write(i2s->regmap, stream_reg, stream_ctrl);
- regmap_write(i2s->regmap, TEGRA210_I2S_CTRL, i2s_ctrl);
+ regmap_write(i2s->regmap, TEGRA210_I2S_CTRL + i2s->soc_data->i2s_ctrl_offset, i2s_ctrl);
return 0;
}
@@ -135,19 +151,16 @@ static int tegra210_i2s_init(struct snd_soc_dapm_widget *w,
struct device *dev = compnt->dev;
struct tegra210_i2s *i2s = dev_get_drvdata(dev);
unsigned int val, status_reg;
- bool is_playback;
+ int stream;
int err;
- switch (w->reg) {
- case TEGRA210_I2S_RX_ENABLE:
- is_playback = true;
+ if (w->reg == TEGRA210_I2S_RX_ENABLE) {
+ stream = SNDRV_PCM_STREAM_PLAYBACK;
status_reg = TEGRA210_I2S_RX_STATUS;
- break;
- case TEGRA210_I2S_TX_ENABLE:
- is_playback = false;
- status_reg = TEGRA210_I2S_TX_STATUS;
- break;
- default:
+ } else if (w->reg == (TEGRA210_I2S_TX_ENABLE + i2s->soc_data->tx_offset)) {
+ stream = SNDRV_PCM_STREAM_CAPTURE;
+ status_reg = TEGRA210_I2S_TX_STATUS + i2s->soc_data->tx_offset;
+ } else {
return -EINVAL;
}
@@ -157,14 +170,14 @@ static int tegra210_i2s_init(struct snd_soc_dapm_widget *w,
10, 10000);
if (err) {
dev_err(dev, "timeout: previous I2S %s is still active\n",
- is_playback ? "playback" : "capture");
+ snd_pcm_direction_name(stream));
return err;
}
- return tegra210_i2s_sw_reset(compnt, is_playback);
+ return tegra210_i2s_sw_reset(compnt, stream);
}
-static int __maybe_unused tegra210_i2s_runtime_suspend(struct device *dev)
+static int tegra210_i2s_runtime_suspend(struct device *dev)
{
struct tegra210_i2s *i2s = dev_get_drvdata(dev);
@@ -176,7 +189,7 @@ static int __maybe_unused tegra210_i2s_runtime_suspend(struct device *dev)
return 0;
}
-static int __maybe_unused tegra210_i2s_runtime_resume(struct device *dev)
+static int tegra210_i2s_runtime_resume(struct device *dev)
{
struct tegra210_i2s *i2s = dev_get_drvdata(dev);
int err;
@@ -197,7 +210,7 @@ static void tegra210_i2s_set_data_offset(struct tegra210_i2s *i2s,
unsigned int data_offset)
{
/* Capture path */
- regmap_update_bits(i2s->regmap, TEGRA210_I2S_TX_CTRL,
+ regmap_update_bits(i2s->regmap, TEGRA210_I2S_TX_CTRL + i2s->soc_data->tx_offset,
I2S_CTRL_DATA_OFFSET_MASK,
data_offset << I2S_DATA_SHIFT);
@@ -280,7 +293,8 @@ static int tegra210_i2s_set_fmt(struct snd_soc_dai *dai,
return -EINVAL;
}
- regmap_update_bits(i2s->regmap, TEGRA210_I2S_CTRL, mask, val);
+ regmap_update_bits(i2s->regmap, TEGRA210_I2S_CTRL + i2s->soc_data->i2s_ctrl_offset,
+ mask, val);
i2s->dai_fmt = fmt & SND_SOC_DAIFMT_FORMAT_MASK;
@@ -294,10 +308,10 @@ static int tegra210_i2s_set_tdm_slot(struct snd_soc_dai *dai,
struct tegra210_i2s *i2s = snd_soc_dai_get_drvdata(dai);
/* Copy the required tx and rx mask */
- i2s->tx_mask = (tx_mask > DEFAULT_I2S_SLOT_MASK) ?
- DEFAULT_I2S_SLOT_MASK : tx_mask;
- i2s->rx_mask = (rx_mask > DEFAULT_I2S_SLOT_MASK) ?
- DEFAULT_I2S_SLOT_MASK : rx_mask;
+ i2s->tx_mask = (tx_mask > i2s->soc_data->slot_mask) ?
+ i2s->soc_data->slot_mask : tx_mask;
+ i2s->rx_mask = (rx_mask > i2s->soc_data->slot_mask) ?
+ i2s->soc_data->slot_mask : rx_mask;
return 0;
}
@@ -325,8 +339,8 @@ static int tegra210_i2s_put_loopback(struct snd_kcontrol *kcontrol,
i2s->loopback = value;
- regmap_update_bits(i2s->regmap, TEGRA210_I2S_CTRL, I2S_CTRL_LPBK_MASK,
- i2s->loopback << I2S_CTRL_LPBK_SHIFT);
+ regmap_update_bits(i2s->regmap, TEGRA210_I2S_CTRL + i2s->soc_data->i2s_ctrl_offset,
+ I2S_CTRL_LPBK_MASK, i2s->loopback << I2S_CTRL_LPBK_SHIFT);
return 1;
}
@@ -362,9 +376,9 @@ static int tegra210_i2s_put_fsync_width(struct snd_kcontrol *kcontrol,
* cases mixer control is used to update custom values. A value
* of "N" here means, width is "N + 1" bit clock wide.
*/
- regmap_update_bits(i2s->regmap, TEGRA210_I2S_CTRL,
- I2S_CTRL_FSYNC_WIDTH_MASK,
- i2s->fsync_width << I2S_FSYNC_WIDTH_SHIFT);
+ regmap_update_bits(i2s->regmap, TEGRA210_I2S_CTRL + i2s->soc_data->i2s_ctrl_offset,
+ i2s->soc_data->fsync_width_mask,
+ i2s->fsync_width << i2s->soc_data->fsync_width_shift);
return 1;
}
@@ -560,7 +574,7 @@ static int tegra210_i2s_set_timing_params(struct device *dev,
return err;
}
- regmap_read(i2s->regmap, TEGRA210_I2S_CTRL, &val);
+ regmap_read(i2s->regmap, TEGRA210_I2S_CTRL + i2s->soc_data->i2s_ctrl_offset, &val);
/*
* For LRCK mode, channel bit count depends on number of bit clocks
@@ -576,7 +590,7 @@ static int tegra210_i2s_set_timing_params(struct device *dev,
case I2S_CTRL_FRAME_FMT_FSYNC_MODE:
bit_count = (bclk_rate / srate) - 1;
- tegra210_i2s_set_slot_ctrl(i2s->regmap, channels,
+ tegra210_i2s_set_slot_ctrl(i2s, channels,
i2s->tx_mask, i2s->rx_mask);
break;
default:
@@ -589,7 +603,7 @@ static int tegra210_i2s_set_timing_params(struct device *dev,
return -EINVAL;
}
- regmap_write(i2s->regmap, TEGRA210_I2S_TIMING,
+ regmap_write(i2s->regmap, TEGRA210_I2S_TIMING + i2s->soc_data->i2s_ctrl_offset,
bit_count << I2S_TIMING_CH_BIT_CNT_SHIFT);
return 0;
@@ -603,6 +617,7 @@ static int tegra210_i2s_hw_params(struct snd_pcm_substream *substream,
struct tegra210_i2s *i2s = snd_soc_dai_get_drvdata(dai);
unsigned int sample_size, channels, srate, val, reg, path;
struct tegra_cif_conf cif_conf;
+ snd_pcm_format_t sample_format;
memset(&cif_conf, 0, sizeof(struct tegra_cif_conf));
@@ -615,33 +630,62 @@ static int tegra210_i2s_hw_params(struct snd_pcm_substream *substream,
cif_conf.audio_ch = channels;
cif_conf.client_ch = channels;
+ if (i2s->client_channels)
+ cif_conf.client_ch = i2s->client_channels;
+ /* AHUB CIF Audio bits configs */
switch (params_format(params)) {
case SNDRV_PCM_FORMAT_S8:
+ cif_conf.audio_bits = TEGRA_ACIF_BITS_8;
+ break;
+ case SNDRV_PCM_FORMAT_S16_LE:
+ cif_conf.audio_bits = TEGRA_ACIF_BITS_16;
+ break;
+ case SNDRV_PCM_FORMAT_S24_LE:
+ case SNDRV_PCM_FORMAT_S32_LE:
+ cif_conf.audio_bits = TEGRA_ACIF_BITS_32;
+ break;
+ default:
+ dev_err(dev, "unsupported params audio bit format!\n");
+ return -EOPNOTSUPP;
+ }
+
+ sample_format = params_format(params);
+ if (i2s->client_sample_format >= 0)
+ sample_format = (snd_pcm_format_t)i2s->client_sample_format;
+
+ /*
+ * Format of the I2S for sending/receiving the audio
+ * to/from external device.
+ */
+ switch (sample_format) {
+ case SNDRV_PCM_FORMAT_S8:
val = I2S_BITS_8;
sample_size = 8;
- cif_conf.audio_bits = TEGRA_ACIF_BITS_8;
cif_conf.client_bits = TEGRA_ACIF_BITS_8;
break;
case SNDRV_PCM_FORMAT_S16_LE:
val = I2S_BITS_16;
sample_size = 16;
- cif_conf.audio_bits = TEGRA_ACIF_BITS_16;
cif_conf.client_bits = TEGRA_ACIF_BITS_16;
break;
+ case SNDRV_PCM_FORMAT_S24_LE:
+ val = I2S_BITS_24;
+ sample_size = 32;
+ cif_conf.client_bits = TEGRA_ACIF_BITS_24;
+ break;
case SNDRV_PCM_FORMAT_S32_LE:
val = I2S_BITS_32;
sample_size = 32;
- cif_conf.audio_bits = TEGRA_ACIF_BITS_32;
cif_conf.client_bits = TEGRA_ACIF_BITS_32;
break;
default:
- dev_err(dev, "unsupported format!\n");
+ dev_err(dev, "unsupported client bit format!\n");
return -EOPNOTSUPP;
}
/* Program sample size */
- regmap_update_bits(i2s->regmap, TEGRA210_I2S_CTRL,
+ regmap_update_bits(i2s->regmap, TEGRA210_I2S_CTRL + i2s->soc_data->i2s_ctrl_offset,
I2S_CTRL_BIT_SIZE_MASK, val);
srate = params_rate(params);
@@ -665,13 +709,16 @@ static int tegra210_i2s_hw_params(struct snd_pcm_substream *substream,
reg = TEGRA210_I2S_RX_CIF_CTRL;
} else {
- reg = TEGRA210_I2S_TX_CIF_CTRL;
+ reg = TEGRA210_I2S_TX_CIF_CTRL + i2s->soc_data->tx_offset;
}
cif_conf.mono_conv = i2s->mono_to_stereo[path];
cif_conf.stereo_conv = i2s->stereo_to_mono[path];
- tegra_set_cif(i2s->regmap, reg, &cif_conf);
+ if (i2s->soc_data->max_ch == TEGRA264_I2S_MAX_CHANNEL)
+ tegra264_set_cif(i2s->regmap, reg, &cif_conf);
+ else
+ tegra_set_cif(i2s->regmap, reg, &cif_conf);
return tegra210_i2s_set_timing_params(dev, sample_size, srate,
cif_conf.client_ch);
@@ -694,6 +741,7 @@ static struct snd_soc_dai_driver tegra210_i2s_dais[] = {
.rates = SNDRV_PCM_RATE_8000_192000,
.formats = SNDRV_PCM_FMTBIT_S8 |
SNDRV_PCM_FMTBIT_S16_LE |
+ SNDRV_PCM_FMTBIT_S24_LE |
SNDRV_PCM_FMTBIT_S32_LE,
},
.capture = {
@@ -703,6 +751,7 @@ static struct snd_soc_dai_driver tegra210_i2s_dais[] = {
.rates = SNDRV_PCM_RATE_8000_192000,
.formats = SNDRV_PCM_FMTBIT_S8 |
SNDRV_PCM_FMTBIT_S16_LE |
+ SNDRV_PCM_FMTBIT_S24_LE |
SNDRV_PCM_FMTBIT_S32_LE,
},
},
@@ -715,6 +764,7 @@ static struct snd_soc_dai_driver tegra210_i2s_dais[] = {
.rates = SNDRV_PCM_RATE_8000_192000,
.formats = SNDRV_PCM_FMTBIT_S8 |
SNDRV_PCM_FMTBIT_S16_LE |
+ SNDRV_PCM_FMTBIT_S24_LE |
SNDRV_PCM_FMTBIT_S32_LE,
},
.capture = {
@@ -724,6 +774,7 @@ static struct snd_soc_dai_driver tegra210_i2s_dais[] = {
.rates = SNDRV_PCM_RATE_8000_192000,
.formats = SNDRV_PCM_FMTBIT_S8 |
SNDRV_PCM_FMTBIT_S16_LE |
+ SNDRV_PCM_FMTBIT_S24_LE |
SNDRV_PCM_FMTBIT_S32_LE,
},
.ops = &tegra210_i2s_dai_ops,
@@ -772,13 +823,20 @@ static const struct snd_kcontrol_new tegra210_i2s_controls[] = {
tegra210_i2s_put_bclk_ratio),
};
-static const struct snd_soc_dapm_widget tegra210_i2s_widgets[] = {
- SND_SOC_DAPM_AIF_IN_E("RX", NULL, 0, TEGRA210_I2S_RX_ENABLE,
- 0, 0, tegra210_i2s_init, SND_SOC_DAPM_PRE_PMU),
- SND_SOC_DAPM_AIF_OUT_E("TX", NULL, 0, TEGRA210_I2S_TX_ENABLE,
- 0, 0, tegra210_i2s_init, SND_SOC_DAPM_PRE_PMU),
- SND_SOC_DAPM_MIC("MIC", NULL),
+#define TEGRA_I2S_WIDGETS(tx_enable_reg) \
+ SND_SOC_DAPM_AIF_IN_E("RX", NULL, 0, TEGRA210_I2S_RX_ENABLE, \
+ 0, 0, tegra210_i2s_init, SND_SOC_DAPM_PRE_PMU), \
+ SND_SOC_DAPM_AIF_OUT_E("TX", NULL, 0, tx_enable_reg, \
+ 0, 0, tegra210_i2s_init, SND_SOC_DAPM_PRE_PMU), \
+ SND_SOC_DAPM_MIC("MIC", NULL), \
SND_SOC_DAPM_SPK("SPK", NULL),
+
+static const struct snd_soc_dapm_widget tegra210_i2s_widgets[] = {
+ TEGRA_I2S_WIDGETS(TEGRA210_I2S_TX_ENABLE)
+};
+
+static const struct snd_soc_dapm_widget tegra264_i2s_widgets[] = {
+ TEGRA_I2S_WIDGETS(TEGRA264_I2S_TX_ENABLE)
};
static const struct snd_soc_dapm_route tegra210_i2s_routes[] = {
@@ -805,6 +863,15 @@ static const struct snd_soc_component_driver tegra210_i2s_cmpnt = {
.num_controls = ARRAY_SIZE(tegra210_i2s_controls),
};
+static const struct snd_soc_component_driver tegra264_i2s_cmpnt = {
+ .dapm_widgets = tegra264_i2s_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(tegra264_i2s_widgets),
+ .dapm_routes = tegra210_i2s_routes,
+ .num_dapm_routes = ARRAY_SIZE(tegra210_i2s_routes),
+ .controls = tegra210_i2s_controls,
+ .num_controls = ARRAY_SIZE(tegra210_i2s_controls),
+};
+
static bool tegra210_i2s_wr_reg(struct device *dev, unsigned int reg)
{
switch (reg) {
@@ -859,7 +926,68 @@ static bool tegra210_i2s_volatile_reg(struct device *dev, unsigned int reg)
}
}
-static const struct regmap_config tegra210_i2s_regmap_config = {
+static bool tegra264_i2s_wr_reg(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case TEGRA210_I2S_RX_ENABLE ... TEGRA210_I2S_RX_SOFT_RESET:
+ case TEGRA210_I2S_RX_INT_MASK ... TEGRA264_I2S_RX_CYA:
+ case TEGRA264_I2S_TX_ENABLE ... TEGRA264_I2S_TX_SOFT_RESET:
+ case TEGRA264_I2S_TX_INT_MASK ... TEGRA264_I2S_TX_FIFO_RD_ACCESS_MODE:
+ case TEGRA264_I2S_TX_FIFO_THRESHOLD ... TEGRA264_I2S_TX_CYA:
+ case TEGRA264_I2S_ENABLE ... TEGRA264_I2S_CG:
+ case TEGRA264_I2S_INT_SET ... TEGRA264_I2S_INT_MASK:
+ case TEGRA264_I2S_CTRL ... TEGRA264_I2S_CYA:
+ return true;
+ default:
+ return false;
+ };
+}
+
+static bool tegra264_i2s_rd_reg(struct device *dev, unsigned int reg)
+{
+ if (tegra264_i2s_wr_reg(dev, reg))
+ return true;
+
+ switch (reg) {
+ case TEGRA210_I2S_RX_STATUS:
+ case TEGRA210_I2S_RX_INT_STATUS:
+ case TEGRA264_I2S_RX_CIF_FIFO_STATUS:
+ case TEGRA264_I2S_TX_STATUS:
+ case TEGRA264_I2S_TX_INT_STATUS:
+ case TEGRA264_I2S_TX_FIFO_RD_DATA:
+ case TEGRA264_I2S_TX_CIF_FIFO_STATUS:
+ case TEGRA264_I2S_STATUS:
+ case TEGRA264_I2S_INT_STATUS:
+ case TEGRA264_I2S_PIO_MODE_ENABLE:
+ case TEGRA264_I2S_PAD_MACRO_STATUS:
+ return true;
+ default:
+ return false;
+ };
+}
+
+static bool tegra264_i2s_volatile_reg(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case TEGRA210_I2S_RX_SOFT_RESET:
+ case TEGRA210_I2S_RX_STATUS:
+ case TEGRA210_I2S_RX_INT_STATUS:
+ case TEGRA264_I2S_RX_CIF_FIFO_STATUS:
+ case TEGRA264_I2S_TX_STATUS:
+ case TEGRA264_I2S_TX_INT_STATUS:
+ case TEGRA264_I2S_TX_FIFO_RD_DATA:
+ case TEGRA264_I2S_TX_CIF_FIFO_STATUS:
+ case TEGRA264_I2S_STATUS:
+ case TEGRA264_I2S_INT_STATUS:
+ case TEGRA264_I2S_TX_SOFT_RESET:
+ case TEGRA264_I2S_PAD_MACRO_STATUS:
+ return true;
+ default:
+ return false;
+ };
+}
+
+static const struct regmap_config tegra210_regmap_conf = {
.reg_bits = 32,
.reg_stride = 4,
.val_bits = 32,
@@ -872,21 +1000,70 @@ static const struct regmap_config tegra210_i2s_regmap_config = {
.cache_type = REGCACHE_FLAT,
};
+/*
+ * The AHUB HW modules are interconnected with CIF which are capable of
+ * supporting Channel and Sample bit format conversion. This needs different
+ * CIF Audio and client configuration. As one of the config comes from
+ * params_channels() or params_format(), the extra configuration is passed from
+ * CIF Port of DT I2S node which can help to perform this conversion.
+ *
+ * 4ch audio = 4ch client = 2ch 2ch
+ * -----> ADMAIF -----------> CIF -------------> I2S ---->
+ */
+static void tegra210_parse_client_convert(struct device *dev)
+{
+ struct tegra210_i2s *i2s = dev_get_drvdata(dev);
+ struct device_node *ports, *ep;
+ struct simple_util_data data = {};
+ int cif_port = 0;
+
+ ports = of_get_child_by_name(dev->of_node, "ports");
+ if (ports) {
+ ep = of_graph_get_endpoint_by_regs(ports, cif_port, -1);
+ if (ep) {
+ simple_util_parse_convert(ep, NULL, &data);
+ of_node_put(ep);
+ }
+ of_node_put(ports);
+ }
+
+ if (data.convert_channels)
+ i2s->client_channels = data.convert_channels;
+
+ if (data.convert_sample_format)
+ i2s->client_sample_format = simple_util_get_sample_fmt(&data);
+}
+
+static const struct regmap_config tegra264_regmap_conf = {
+ .reg_bits = 32,
+ .reg_stride = 4,
+ .val_bits = 32,
+ .max_register = TEGRA264_I2S_PAD_MACRO_STATUS,
+ .writeable_reg = tegra264_i2s_wr_reg,
+ .readable_reg = tegra264_i2s_rd_reg,
+ .volatile_reg = tegra264_i2s_volatile_reg,
+ .reg_defaults = tegra264_i2s_reg_defaults,
+ .num_reg_defaults = ARRAY_SIZE(tegra264_i2s_reg_defaults),
+ .cache_type = REGCACHE_FLAT,
+};
+
static int tegra210_i2s_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct tegra210_i2s *i2s;
void __iomem *regs;
- int err;
+ int err, id;
i2s = devm_kzalloc(dev, sizeof(*i2s), GFP_KERNEL);
if (!i2s)
return -ENOMEM;
+ i2s->soc_data = of_device_get_match_data(&pdev->dev);
i2s->rx_fifo_th = DEFAULT_I2S_RX_FIFO_THRESHOLD;
- i2s->tx_mask = DEFAULT_I2S_SLOT_MASK;
- i2s->rx_mask = DEFAULT_I2S_SLOT_MASK;
+ i2s->tx_mask = i2s->soc_data->slot_mask;
+ i2s->rx_mask = i2s->soc_data->slot_mask;
i2s->loopback = false;
+ i2s->client_sample_format = -EINVAL;
dev_set_drvdata(dev, i2s);
@@ -910,15 +1087,23 @@ static int tegra210_i2s_probe(struct platform_device *pdev)
return PTR_ERR(regs);
i2s->regmap = devm_regmap_init_mmio(dev, regs,
- &tegra210_i2s_regmap_config);
+ i2s->soc_data->regmap_conf);
if (IS_ERR(i2s->regmap)) {
dev_err(dev, "regmap init failed\n");
return PTR_ERR(i2s->regmap);
}
+ tegra210_parse_client_convert(dev);
+
regcache_cache_only(i2s->regmap, true);
- err = devm_snd_soc_register_component(dev, &tegra210_i2s_cmpnt,
+ /* Update the dais max channel as per soc */
+ for (id = 0; id < ARRAY_SIZE(tegra210_i2s_dais); id++) {
+ tegra210_i2s_dais[id].playback.channels_max = i2s->soc_data->max_ch;
+ tegra210_i2s_dais[id].capture.channels_max = i2s->soc_data->max_ch;
+ }
+
+ err = devm_snd_soc_register_component(dev, i2s->soc_data->i2s_cmpnt,
tegra210_i2s_dais,
ARRAY_SIZE(tegra210_i2s_dais));
if (err) {
@@ -937,14 +1122,36 @@ static void tegra210_i2s_remove(struct platform_device *pdev)
}
static const struct dev_pm_ops tegra210_i2s_pm_ops = {
- SET_RUNTIME_PM_OPS(tegra210_i2s_runtime_suspend,
- tegra210_i2s_runtime_resume, NULL)
- SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
- pm_runtime_force_resume)
+ RUNTIME_PM_OPS(tegra210_i2s_runtime_suspend,
+ tegra210_i2s_runtime_resume, NULL)
+ SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, pm_runtime_force_resume)
+};
+
+static const struct tegra_i2s_soc_data soc_data_tegra210 = {
+ .regmap_conf = &tegra210_regmap_conf,
+ .i2s_cmpnt = &tegra210_i2s_cmpnt,
+ .max_ch = TEGRA210_I2S_MAX_CHANNEL,
+ .tx_offset = TEGRA210_I2S_TX_OFFSET,
+ .i2s_ctrl_offset = TEGRA210_I2S_CTRL_OFFSET,
+ .fsync_width_mask = I2S_CTRL_FSYNC_WIDTH_MASK,
+ .fsync_width_shift = I2S_FSYNC_WIDTH_SHIFT,
+ .slot_mask = DEFAULT_I2S_SLOT_MASK,
+};
+
+static const struct tegra_i2s_soc_data soc_data_tegra264 = {
+ .regmap_conf = &tegra264_regmap_conf,
+ .i2s_cmpnt = &tegra264_i2s_cmpnt,
+ .max_ch = TEGRA264_I2S_MAX_CHANNEL,
+ .tx_offset = TEGRA264_I2S_TX_OFFSET,
+ .i2s_ctrl_offset = TEGRA264_I2S_CTRL_OFFSET,
+ .fsync_width_mask = TEGRA264_I2S_CTRL_FSYNC_WIDTH_MASK,
+ .fsync_width_shift = TEGRA264_I2S_FSYNC_WIDTH_SHIFT,
+ .slot_mask = TEGRA264_DEFAULT_I2S_SLOT_MASK,
};
static const struct of_device_id tegra210_i2s_of_match[] = {
- { .compatible = "nvidia,tegra210-i2s" },
+ { .compatible = "nvidia,tegra210-i2s", .data = &soc_data_tegra210 },
+ { .compatible = "nvidia,tegra264-i2s", .data = &soc_data_tegra264 },
{},
};
MODULE_DEVICE_TABLE(of, tegra210_i2s_of_match);
@@ -953,10 +1160,10 @@ static struct platform_driver tegra210_i2s_driver = {
.driver = {
.name = "tegra210-i2s",
.of_match_table = tegra210_i2s_of_match,
- .pm = &tegra210_i2s_pm_ops,
+ .pm = pm_ptr(&tegra210_i2s_pm_ops),
},
.probe = tegra210_i2s_probe,
- .remove_new = tegra210_i2s_remove,
+ .remove = tegra210_i2s_remove,
};
module_platform_driver(tegra210_i2s_driver)
diff --git a/sound/soc/tegra/tegra210_i2s.h b/sound/soc/tegra/tegra210_i2s.h
index 030d70c45e18..42be2137342c 100644
--- a/sound/soc/tegra/tegra210_i2s.h
+++ b/sound/soc/tegra/tegra210_i2s.h
@@ -1,8 +1,8 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * tegra210_i2s.h - Definitions for Tegra210 I2S driver
+/* SPDX-License-Identifier: GPL-2.0-only
+ * SPDX-FileCopyrightText: Copyright (c) 2020-2025 NVIDIA CORPORATION & AFFILIATES.
+ * All rights reserved.
*
- * Copyright (c) 2020 NVIDIA CORPORATION. All rights reserved.
+ * tegra210_i2s.h - Definitions for Tegra210 I2S driver
*
*/
@@ -47,9 +47,38 @@
#define TEGRA210_I2S_CLK_TRIM 0xac
#define TEGRA210_I2S_CYA 0xb0
+/* T264 specific registers */
+#define TEGRA264_I2S_RX_FIFO_WR_ACCESS_MODE 0x30
+#define TEGRA264_I2S_RX_CYA 0x3c
+#define TEGRA264_I2S_RX_CIF_FIFO_STATUS 0x40
+#define TEGRA264_I2S_TX_ENABLE 0x80
+#define TEGRA264_I2S_TX_SOFT_RESET 0x84
+#define TEGRA264_I2S_TX_STATUS 0x8c
+#define TEGRA264_I2S_TX_INT_STATUS 0x90
+#define TEGRA264_I2S_TX_INT_MASK 0x94
+#define TEGRA264_I2S_TX_CIF_CTRL 0xa0
+#define TEGRA264_I2S_TX_FIFO_RD_ACCESS_MODE 0xb0
+#define TEGRA264_I2S_TX_FIFO_RD_DATA 0xb4
+#define TEGRA264_I2S_TX_FIFO_THRESHOLD 0xb8
+#define TEGRA264_I2S_TX_CYA 0xbc
+#define TEGRA264_I2S_TX_CIF_FIFO_STATUS 0xc0
+#define TEGRA264_I2S_ENABLE 0x100
+#define TEGRA264_I2S_CG 0x108
+#define TEGRA264_I2S_STATUS 0x10c
+#define TEGRA264_I2S_INT_STATUS 0x110
+#define TEGRA264_I2S_INT_SET 0x114
+#define TEGRA264_I2S_INT_MASK 0x11c
+#define TEGRA264_I2S_CTRL 0x12c
+#define TEGRA264_I2S_TIMING 0x130
+#define TEGRA264_I2S_CYA 0x13c
+#define TEGRA264_I2S_PIO_MODE_ENABLE 0x140
+#define TEGRA264_I2S_PAD_MACRO_STATUS 0x144
+
/* Bit fields, shifts and masks */
#define I2S_DATA_SHIFT 8
#define I2S_CTRL_DATA_OFFSET_MASK (0x7ff << I2S_DATA_SHIFT)
+#define TEGRA264_I2S_FSYNC_WIDTH_SHIFT 23
+#define TEGRA264_I2S_CTRL_FSYNC_WIDTH_MASK (0x1ff << TEGRA264_I2S_FSYNC_WIDTH_SHIFT)
#define I2S_EN_SHIFT 0
#define I2S_EN_MASK BIT(I2S_EN_SHIFT)
@@ -87,6 +116,7 @@
#define I2S_BITS_8 1
#define I2S_BITS_16 3
+#define I2S_BITS_24 5
#define I2S_BITS_32 7
#define I2S_CTRL_BIT_SIZE_MASK 0x7
@@ -101,6 +131,14 @@
#define DEFAULT_I2S_RX_FIFO_THRESHOLD 3
#define DEFAULT_I2S_SLOT_MASK 0xffff
+#define TEGRA210_I2S_TX_OFFSET 0
+#define TEGRA210_I2S_CTRL_OFFSET 0
+#define TEGRA210_I2S_MAX_CHANNEL 16
+
+#define TEGRA264_DEFAULT_I2S_SLOT_MASK 0xffffffff
+#define TEGRA264_I2S_TX_OFFSET 0x40
+#define TEGRA264_I2S_CTRL_OFFSET 0x8c
+#define TEGRA264_I2S_MAX_CHANNEL 32
enum tegra210_i2s_path {
I2S_RX_PATH,
@@ -108,10 +146,24 @@ enum tegra210_i2s_path {
I2S_PATHS,
};
+struct tegra_i2s_soc_data {
+ const struct regmap_config *regmap_conf;
+ const struct snd_soc_component_driver *i2s_cmpnt;
+ unsigned int max_ch;
+ unsigned int tx_offset;
+ unsigned int i2s_ctrl_offset;
+ unsigned int fsync_width_mask;
+ unsigned int fsync_width_shift;
+ unsigned int slot_mask;
+};
+
struct tegra210_i2s {
+ const struct tegra_i2s_soc_data *soc_data;
struct clk *clk_i2s;
struct clk *clk_sync_input;
struct regmap *regmap;
+ int client_sample_format;
+ unsigned int client_channels;
unsigned int stereo_to_mono[I2S_PATHS];
unsigned int mono_to_stereo[I2S_PATHS];
unsigned int dai_fmt;
diff --git a/sound/soc/tegra/tegra210_mixer.c b/sound/soc/tegra/tegra210_mixer.c
index 024614f6ec0b..95d69a7e027f 100644
--- a/sound/soc/tegra/tegra210_mixer.c
+++ b/sound/soc/tegra/tegra210_mixer.c
@@ -1,8 +1,8 @@
// SPDX-License-Identifier: GPL-2.0-only
+// SPDX-FileCopyrightText: Copyright (c) 2021-2024 NVIDIA CORPORATION & AFFILIATES.
+// All rights reserved.
//
// tegra210_mixer.c - Tegra210 MIXER driver
-//
-// Copyright (c) 2021 NVIDIA CORPORATION. All rights reserved.
#include <linux/clk.h>
#include <linux/device.h>
@@ -73,7 +73,7 @@ static const struct tegra210_mixer_gain_params gain_params = {
{ 0, 0, 0x400, 0x8000000 },
};
-static int __maybe_unused tegra210_mixer_runtime_suspend(struct device *dev)
+static int tegra210_mixer_runtime_suspend(struct device *dev)
{
struct tegra210_mixer *mixer = dev_get_drvdata(dev);
@@ -83,7 +83,7 @@ static int __maybe_unused tegra210_mixer_runtime_suspend(struct device *dev)
return 0;
}
-static int __maybe_unused tegra210_mixer_runtime_resume(struct device *dev)
+static int tegra210_mixer_runtime_resume(struct device *dev)
{
struct tegra210_mixer *mixer = dev_get_drvdata(dev);
@@ -248,6 +248,7 @@ static int tegra210_mixer_set_audio_cif(struct tegra210_mixer *mixer,
case SNDRV_PCM_FORMAT_S16_LE:
audio_bits = TEGRA_ACIF_BITS_16;
break;
+ case SNDRV_PCM_FORMAT_S24_LE:
case SNDRV_PCM_FORMAT_S32_LE:
audio_bits = TEGRA_ACIF_BITS_32;
break;
@@ -312,6 +313,7 @@ static const struct snd_soc_dai_ops tegra210_mixer_in_dai_ops = {
.rates = SNDRV_PCM_RATE_8000_192000, \
.formats = SNDRV_PCM_FMTBIT_S8 | \
SNDRV_PCM_FMTBIT_S16_LE | \
+ SNDRV_PCM_FMTBIT_S24_LE | \
SNDRV_PCM_FMTBIT_S32_LE, \
}, \
.capture = { \
@@ -321,6 +323,7 @@ static const struct snd_soc_dai_ops tegra210_mixer_in_dai_ops = {
.rates = SNDRV_PCM_RATE_8000_192000, \
.formats = SNDRV_PCM_FMTBIT_S8 | \
SNDRV_PCM_FMTBIT_S16_LE | \
+ SNDRV_PCM_FMTBIT_S24_LE | \
SNDRV_PCM_FMTBIT_S32_LE, \
}, \
.ops = &tegra210_mixer_in_dai_ops, \
@@ -336,6 +339,7 @@ static const struct snd_soc_dai_ops tegra210_mixer_in_dai_ops = {
.rates = SNDRV_PCM_RATE_8000_192000, \
.formats = SNDRV_PCM_FMTBIT_S8 | \
SNDRV_PCM_FMTBIT_S16_LE | \
+ SNDRV_PCM_FMTBIT_S24_LE | \
SNDRV_PCM_FMTBIT_S32_LE, \
}, \
.capture = { \
@@ -345,6 +349,7 @@ static const struct snd_soc_dai_ops tegra210_mixer_in_dai_ops = {
.rates = SNDRV_PCM_RATE_8000_192000, \
.formats = SNDRV_PCM_FMTBIT_S8 | \
SNDRV_PCM_FMTBIT_S16_LE | \
+ SNDRV_PCM_FMTBIT_S24_LE | \
SNDRV_PCM_FMTBIT_S32_LE, \
}, \
.ops = &tegra210_mixer_out_dai_ops, \
@@ -661,20 +666,19 @@ static void tegra210_mixer_platform_remove(struct platform_device *pdev)
}
static const struct dev_pm_ops tegra210_mixer_pm_ops = {
- SET_RUNTIME_PM_OPS(tegra210_mixer_runtime_suspend,
- tegra210_mixer_runtime_resume, NULL)
- SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
- pm_runtime_force_resume)
+ RUNTIME_PM_OPS(tegra210_mixer_runtime_suspend,
+ tegra210_mixer_runtime_resume, NULL)
+ SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, pm_runtime_force_resume)
};
static struct platform_driver tegra210_mixer_driver = {
.driver = {
.name = "tegra210_mixer",
.of_match_table = tegra210_mixer_of_match,
- .pm = &tegra210_mixer_pm_ops,
+ .pm = pm_ptr(&tegra210_mixer_pm_ops),
},
.probe = tegra210_mixer_platform_probe,
- .remove_new = tegra210_mixer_platform_remove,
+ .remove = tegra210_mixer_platform_remove,
};
module_platform_driver(tegra210_mixer_driver);
diff --git a/sound/soc/tegra/tegra210_mvc.c b/sound/soc/tegra/tegra210_mvc.c
index b89f5edafa03..35b14c8396f4 100644
--- a/sound/soc/tegra/tegra210_mvc.c
+++ b/sound/soc/tegra/tegra210_mvc.c
@@ -1,8 +1,8 @@
// SPDX-License-Identifier: GPL-2.0-only
+// SPDX-FileCopyrightText: Copyright (c) 2021-2024 NVIDIA CORPORATION & AFFILIATES.
+// All rights reserved.
//
// tegra210_mvc.c - Tegra210 MVC driver
-//
-// Copyright (c) 2021 NVIDIA CORPORATION. All rights reserved.
#include <linux/clk.h>
#include <linux/device.h>
@@ -47,7 +47,7 @@ static const struct tegra210_mvc_gain_params gain_params = {
.duration_inv = 14316558,
};
-static int __maybe_unused tegra210_mvc_runtime_suspend(struct device *dev)
+static int tegra210_mvc_runtime_suspend(struct device *dev)
{
struct tegra210_mvc *mvc = dev_get_drvdata(dev);
@@ -59,7 +59,7 @@ static int __maybe_unused tegra210_mvc_runtime_suspend(struct device *dev)
return 0;
}
-static int __maybe_unused tegra210_mvc_runtime_resume(struct device *dev)
+static int tegra210_mvc_runtime_resume(struct device *dev)
{
struct tegra210_mvc *mvc = dev_get_drvdata(dev);
@@ -441,6 +441,7 @@ static int tegra210_mvc_set_audio_cif(struct tegra210_mvc *mvc,
case SNDRV_PCM_FORMAT_S16_LE:
audio_bits = TEGRA_ACIF_BITS_16;
break;
+ case SNDRV_PCM_FORMAT_S24_LE:
case SNDRV_PCM_FORMAT_S32_LE:
audio_bits = TEGRA_ACIF_BITS_32;
break;
@@ -569,6 +570,7 @@ static struct snd_soc_dai_driver tegra210_mvc_dais[] = {
.rates = SNDRV_PCM_RATE_8000_192000,
.formats = SNDRV_PCM_FMTBIT_S8 |
SNDRV_PCM_FMTBIT_S16_LE |
+ SNDRV_PCM_FMTBIT_S24_LE |
SNDRV_PCM_FMTBIT_S32_LE,
},
.capture = {
@@ -578,6 +580,7 @@ static struct snd_soc_dai_driver tegra210_mvc_dais[] = {
.rates = SNDRV_PCM_RATE_8000_192000,
.formats = SNDRV_PCM_FMTBIT_S8 |
SNDRV_PCM_FMTBIT_S16_LE |
+ SNDRV_PCM_FMTBIT_S24_LE |
SNDRV_PCM_FMTBIT_S32_LE,
},
},
@@ -592,6 +595,7 @@ static struct snd_soc_dai_driver tegra210_mvc_dais[] = {
.rates = SNDRV_PCM_RATE_8000_192000,
.formats = SNDRV_PCM_FMTBIT_S8 |
SNDRV_PCM_FMTBIT_S16_LE |
+ SNDRV_PCM_FMTBIT_S24_LE |
SNDRV_PCM_FMTBIT_S32_LE,
},
.capture = {
@@ -601,6 +605,7 @@ static struct snd_soc_dai_driver tegra210_mvc_dais[] = {
.rates = SNDRV_PCM_RATE_8000_192000,
.formats = SNDRV_PCM_FMTBIT_S8 |
SNDRV_PCM_FMTBIT_S16_LE |
+ SNDRV_PCM_FMTBIT_S24_LE |
SNDRV_PCM_FMTBIT_S32_LE,
},
.ops = &tegra210_mvc_dai_ops,
@@ -753,20 +758,19 @@ static void tegra210_mvc_platform_remove(struct platform_device *pdev)
}
static const struct dev_pm_ops tegra210_mvc_pm_ops = {
- SET_RUNTIME_PM_OPS(tegra210_mvc_runtime_suspend,
- tegra210_mvc_runtime_resume, NULL)
- SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
- pm_runtime_force_resume)
+ RUNTIME_PM_OPS(tegra210_mvc_runtime_suspend,
+ tegra210_mvc_runtime_resume, NULL)
+ SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, pm_runtime_force_resume)
};
static struct platform_driver tegra210_mvc_driver = {
.driver = {
.name = "tegra210-mvc",
.of_match_table = tegra210_mvc_of_match,
- .pm = &tegra210_mvc_pm_ops,
+ .pm = pm_ptr(&tegra210_mvc_pm_ops),
},
.probe = tegra210_mvc_platform_probe,
- .remove_new = tegra210_mvc_platform_remove,
+ .remove = tegra210_mvc_platform_remove,
};
module_platform_driver(tegra210_mvc_driver)
diff --git a/sound/soc/tegra/tegra210_ope.c b/sound/soc/tegra/tegra210_ope.c
index 136ed17f3650..5036bcfe0828 100644
--- a/sound/soc/tegra/tegra210_ope.c
+++ b/sound/soc/tegra/tegra210_ope.c
@@ -1,8 +1,8 @@
// SPDX-License-Identifier: GPL-2.0-only
+// SPDX-FileCopyrightText: Copyright (c) 2022-2024 NVIDIA CORPORATION & AFFILIATES.
+// All rights reserved.
//
// tegra210_ope.c - Tegra210 OPE driver
-//
-// Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved.
#include <linux/clk.h>
#include <linux/device.h>
@@ -47,6 +47,7 @@ static int tegra210_ope_set_audio_cif(struct tegra210_ope *ope,
case SNDRV_PCM_FORMAT_S16_LE:
audio_bits = TEGRA_ACIF_BITS_16;
break;
+ case SNDRV_PCM_FORMAT_S24_LE:
case SNDRV_PCM_FORMAT_S32_LE:
audio_bits = TEGRA_ACIF_BITS_32;
break;
@@ -129,6 +130,7 @@ static struct snd_soc_dai_driver tegra210_ope_dais[] = {
.rates = SNDRV_PCM_RATE_8000_192000,
.formats = SNDRV_PCM_FMTBIT_S8 |
SNDRV_PCM_FMTBIT_S16_LE |
+ SNDRV_PCM_FMTBIT_S24_LE |
SNDRV_PCM_FMTBIT_S32_LE,
},
.capture = {
@@ -138,6 +140,7 @@ static struct snd_soc_dai_driver tegra210_ope_dais[] = {
.rates = SNDRV_PCM_RATE_8000_192000,
.formats = SNDRV_PCM_FMTBIT_S8 |
SNDRV_PCM_FMTBIT_S16_LE |
+ SNDRV_PCM_FMTBIT_S24_LE |
SNDRV_PCM_FMTBIT_S32_LE,
},
},
@@ -150,6 +153,7 @@ static struct snd_soc_dai_driver tegra210_ope_dais[] = {
.rates = SNDRV_PCM_RATE_8000_192000,
.formats = SNDRV_PCM_FMTBIT_S8 |
SNDRV_PCM_FMTBIT_S16_LE |
+ SNDRV_PCM_FMTBIT_S24_LE |
SNDRV_PCM_FMTBIT_S32_LE,
},
.capture = {
@@ -159,6 +163,7 @@ static struct snd_soc_dai_driver tegra210_ope_dais[] = {
.rates = SNDRV_PCM_RATE_8000_192000,
.formats = SNDRV_PCM_FMTBIT_S8 |
SNDRV_PCM_FMTBIT_S16_LE |
+ SNDRV_PCM_FMTBIT_S24_LE |
SNDRV_PCM_FMTBIT_S32_LE,
},
.ops = &tegra210_ope_dai_ops,
@@ -351,7 +356,7 @@ static void tegra210_ope_remove(struct platform_device *pdev)
pm_runtime_disable(&pdev->dev);
}
-static int __maybe_unused tegra210_ope_runtime_suspend(struct device *dev)
+static int tegra210_ope_runtime_suspend(struct device *dev)
{
struct tegra210_ope *ope = dev_get_drvdata(dev);
@@ -369,7 +374,7 @@ static int __maybe_unused tegra210_ope_runtime_suspend(struct device *dev)
return 0;
}
-static int __maybe_unused tegra210_ope_runtime_resume(struct device *dev)
+static int tegra210_ope_runtime_resume(struct device *dev)
{
struct tegra210_ope *ope = dev_get_drvdata(dev);
@@ -388,10 +393,9 @@ static int __maybe_unused tegra210_ope_runtime_resume(struct device *dev)
}
static const struct dev_pm_ops tegra210_ope_pm_ops = {
- SET_RUNTIME_PM_OPS(tegra210_ope_runtime_suspend,
- tegra210_ope_runtime_resume, NULL)
- SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
- pm_runtime_force_resume)
+ RUNTIME_PM_OPS(tegra210_ope_runtime_suspend,
+ tegra210_ope_runtime_resume, NULL)
+ SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, pm_runtime_force_resume)
};
static const struct of_device_id tegra210_ope_of_match[] = {
@@ -404,10 +408,10 @@ static struct platform_driver tegra210_ope_driver = {
.driver = {
.name = "tegra210-ope",
.of_match_table = tegra210_ope_of_match,
- .pm = &tegra210_ope_pm_ops,
+ .pm = pm_ptr(&tegra210_ope_pm_ops),
},
.probe = tegra210_ope_probe,
- .remove_new = tegra210_ope_remove,
+ .remove = tegra210_ope_remove,
};
module_platform_driver(tegra210_ope_driver)
diff --git a/sound/soc/tegra/tegra210_sfc.c b/sound/soc/tegra/tegra210_sfc.c
index 028747c44f37..a0bd36f12c68 100644
--- a/sound/soc/tegra/tegra210_sfc.c
+++ b/sound/soc/tegra/tegra210_sfc.c
@@ -1,8 +1,8 @@
// SPDX-License-Identifier: GPL-2.0-only
+// SPDX-FileCopyrightText: Copyright (c) 2021-2024 NVIDIA CORPORATION & AFFILIATES.
+// All rights reserved.
//
// tegra210_sfc.c - Tegra210 SFC driver
-//
-// Copyright (c) 2021-2023 NVIDIA CORPORATION. All rights reserved.
#include <linux/clk.h>
#include <linux/device.h>
@@ -3056,7 +3056,7 @@ static s32 *coef_addr_table[TEGRA210_SFC_NUM_RATES][TEGRA210_SFC_NUM_RATES] = {
},
};
-static int __maybe_unused tegra210_sfc_runtime_suspend(struct device *dev)
+static int tegra210_sfc_runtime_suspend(struct device *dev)
{
struct tegra210_sfc *sfc = dev_get_drvdata(dev);
@@ -3066,7 +3066,7 @@ static int __maybe_unused tegra210_sfc_runtime_suspend(struct device *dev)
return 0;
}
-static int __maybe_unused tegra210_sfc_runtime_resume(struct device *dev)
+static int tegra210_sfc_runtime_resume(struct device *dev)
{
struct tegra210_sfc *sfc = dev_get_drvdata(dev);
@@ -3133,6 +3133,7 @@ static int tegra210_sfc_set_audio_cif(struct tegra210_sfc *sfc,
case SNDRV_PCM_FORMAT_S16_LE:
audio_bits = TEGRA_ACIF_BITS_16;
break;
+ case SNDRV_PCM_FORMAT_S24_LE:
case SNDRV_PCM_FORMAT_S32_LE:
audio_bits = TEGRA_ACIF_BITS_32;
break;
@@ -3395,6 +3396,7 @@ static struct snd_soc_dai_driver tegra210_sfc_dais[] = {
.rates = SNDRV_PCM_RATE_8000_192000,
.formats = SNDRV_PCM_FMTBIT_S8 |
SNDRV_PCM_FMTBIT_S16_LE |
+ SNDRV_PCM_FMTBIT_S24_LE |
SNDRV_PCM_FMTBIT_S32_LE,
},
.capture = {
@@ -3404,6 +3406,7 @@ static struct snd_soc_dai_driver tegra210_sfc_dais[] = {
.rates = SNDRV_PCM_RATE_8000_192000,
.formats = SNDRV_PCM_FMTBIT_S8 |
SNDRV_PCM_FMTBIT_S16_LE |
+ SNDRV_PCM_FMTBIT_S24_LE |
SNDRV_PCM_FMTBIT_S32_LE,
},
.ops = &tegra210_sfc_in_dai_ops,
@@ -3417,6 +3420,7 @@ static struct snd_soc_dai_driver tegra210_sfc_dais[] = {
.rates = SNDRV_PCM_RATE_8000_192000,
.formats = SNDRV_PCM_FMTBIT_S8 |
SNDRV_PCM_FMTBIT_S16_LE |
+ SNDRV_PCM_FMTBIT_S24_LE |
SNDRV_PCM_FMTBIT_S32_LE,
},
.capture = {
@@ -3426,6 +3430,7 @@ static struct snd_soc_dai_driver tegra210_sfc_dais[] = {
.rates = SNDRV_PCM_RATE_8000_192000,
.formats = SNDRV_PCM_FMTBIT_S8 |
SNDRV_PCM_FMTBIT_S16_LE |
+ SNDRV_PCM_FMTBIT_S24_LE |
SNDRV_PCM_FMTBIT_S32_LE,
},
.ops = &tegra210_sfc_out_dai_ops,
@@ -3618,20 +3623,19 @@ static void tegra210_sfc_platform_remove(struct platform_device *pdev)
}
static const struct dev_pm_ops tegra210_sfc_pm_ops = {
- SET_RUNTIME_PM_OPS(tegra210_sfc_runtime_suspend,
- tegra210_sfc_runtime_resume, NULL)
- SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
- pm_runtime_force_resume)
+ RUNTIME_PM_OPS(tegra210_sfc_runtime_suspend,
+ tegra210_sfc_runtime_resume, NULL)
+ SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, pm_runtime_force_resume)
};
static struct platform_driver tegra210_sfc_driver = {
.driver = {
.name = "tegra210-sfc",
.of_match_table = tegra210_sfc_of_match,
- .pm = &tegra210_sfc_pm_ops,
+ .pm = pm_ptr(&tegra210_sfc_pm_ops),
},
.probe = tegra210_sfc_platform_probe,
- .remove_new = tegra210_sfc_platform_remove,
+ .remove = tegra210_sfc_platform_remove,
};
module_platform_driver(tegra210_sfc_driver)
diff --git a/sound/soc/tegra/tegra30_ahub.c b/sound/soc/tegra/tegra30_ahub.c
index d2e8078e444a..51e5ab6c276b 100644
--- a/sound/soc/tegra/tegra30_ahub.c
+++ b/sound/soc/tegra/tegra30_ahub.c
@@ -40,7 +40,7 @@ static inline void tegra30_audio_write(u32 reg, u32 val)
regmap_write(ahub->regmap_ahub, reg, val);
}
-static __maybe_unused int tegra30_ahub_runtime_suspend(struct device *dev)
+static int tegra30_ahub_runtime_suspend(struct device *dev)
{
regcache_cache_only(ahub->regmap_apbif, true);
regcache_cache_only(ahub->regmap_ahub, true);
@@ -61,7 +61,7 @@ static __maybe_unused int tegra30_ahub_runtime_suspend(struct device *dev)
* stopping streams should dynamically adjust the clock as required. However,
* this is not yet implemented.
*/
-static __maybe_unused int tegra30_ahub_runtime_resume(struct device *dev)
+static int tegra30_ahub_runtime_resume(struct device *dev)
{
int ret;
@@ -600,19 +600,18 @@ static void tegra30_ahub_remove(struct platform_device *pdev)
}
static const struct dev_pm_ops tegra30_ahub_pm_ops = {
- SET_RUNTIME_PM_OPS(tegra30_ahub_runtime_suspend,
- tegra30_ahub_runtime_resume, NULL)
- SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
- pm_runtime_force_resume)
+ RUNTIME_PM_OPS(tegra30_ahub_runtime_suspend,
+ tegra30_ahub_runtime_resume, NULL)
+ SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, pm_runtime_force_resume)
};
static struct platform_driver tegra30_ahub_driver = {
.probe = tegra30_ahub_probe,
- .remove_new = tegra30_ahub_remove,
+ .remove = tegra30_ahub_remove,
.driver = {
.name = DRV_NAME,
.of_match_table = tegra30_ahub_of_match,
- .pm = &tegra30_ahub_pm_ops,
+ .pm = pm_ptr(&tegra30_ahub_pm_ops),
},
};
module_platform_driver(tegra30_ahub_driver);
diff --git a/sound/soc/tegra/tegra30_i2s.c b/sound/soc/tegra/tegra30_i2s.c
index a8ff51d12edb..b121af9ef8ed 100644
--- a/sound/soc/tegra/tegra30_i2s.c
+++ b/sound/soc/tegra/tegra30_i2s.c
@@ -35,7 +35,7 @@
#define DRV_NAME "tegra30-i2s"
-static __maybe_unused int tegra30_i2s_runtime_suspend(struct device *dev)
+static int tegra30_i2s_runtime_suspend(struct device *dev)
{
struct tegra30_i2s *i2s = dev_get_drvdata(dev);
@@ -46,7 +46,7 @@ static __maybe_unused int tegra30_i2s_runtime_suspend(struct device *dev)
return 0;
}
-static __maybe_unused int tegra30_i2s_runtime_resume(struct device *dev)
+static int tegra30_i2s_runtime_resume(struct device *dev)
{
struct tegra30_i2s *i2s = dev_get_drvdata(dev);
int ret;
@@ -547,20 +547,19 @@ static void tegra30_i2s_platform_remove(struct platform_device *pdev)
}
static const struct dev_pm_ops tegra30_i2s_pm_ops = {
- SET_RUNTIME_PM_OPS(tegra30_i2s_runtime_suspend,
- tegra30_i2s_runtime_resume, NULL)
- SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
- pm_runtime_force_resume)
+ RUNTIME_PM_OPS(tegra30_i2s_runtime_suspend,
+ tegra30_i2s_runtime_resume, NULL)
+ SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, pm_runtime_force_resume)
};
static struct platform_driver tegra30_i2s_driver = {
.driver = {
.name = DRV_NAME,
.of_match_table = tegra30_i2s_of_match,
- .pm = &tegra30_i2s_pm_ops,
+ .pm = pm_ptr(&tegra30_i2s_pm_ops),
},
.probe = tegra30_i2s_platform_probe,
- .remove_new = tegra30_i2s_platform_remove,
+ .remove = tegra30_i2s_platform_remove,
};
module_platform_driver(tegra30_i2s_driver);
diff --git a/sound/soc/tegra/tegra_asoc_machine.c b/sound/soc/tegra/tegra_asoc_machine.c
index 192e9692bdf2..62f896772731 100644
--- a/sound/soc/tegra/tegra_asoc_machine.c
+++ b/sound/soc/tegra/tegra_asoc_machine.c
@@ -290,7 +290,7 @@ static unsigned int tegra_machine_mclk_rate_6mhz(unsigned int srate)
static int tegra_machine_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params)
{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0);
struct snd_soc_card *card = rtd->card;
struct tegra_machine *machine = snd_soc_card_get_drvdata(card);
@@ -637,7 +637,7 @@ static struct snd_soc_dai_link tegra_wm8753_dai = {
.stream_name = "WM8753 PCM",
.dai_fmt = SND_SOC_DAIFMT_I2S |
SND_SOC_DAIFMT_NB_NF |
- SND_SOC_DAIFMT_CBS_CFS,
+ SND_SOC_DAIFMT_CBC_CFC,
SND_SOC_DAILINK_REG(wm8753_hifi),
};
@@ -701,7 +701,7 @@ static struct snd_soc_dai_link tegra_max98090_dai = {
.init = tegra_asoc_machine_init,
.dai_fmt = SND_SOC_DAIFMT_I2S |
SND_SOC_DAIFMT_NB_NF |
- SND_SOC_DAIFMT_CBS_CFS,
+ SND_SOC_DAIFMT_CBC_CFC,
SND_SOC_DAILINK_REG(max98090_hifi),
};
@@ -736,7 +736,7 @@ static struct snd_soc_dai_link tegra_max98088_dai = {
.init = tegra_asoc_machine_init,
.dai_fmt = SND_SOC_DAIFMT_I2S |
SND_SOC_DAIFMT_NB_NF |
- SND_SOC_DAIFMT_CBS_CFS,
+ SND_SOC_DAIFMT_CBC_CFC,
SND_SOC_DAILINK_REG(max98088_hifi),
};
@@ -769,7 +769,7 @@ static struct snd_soc_dai_link tegra_sgtl5000_dai = {
.stream_name = "HiFi",
.dai_fmt = SND_SOC_DAIFMT_I2S |
SND_SOC_DAIFMT_NB_NF |
- SND_SOC_DAIFMT_CBS_CFS,
+ SND_SOC_DAIFMT_CBC_CFC,
SND_SOC_DAILINK_REG(sgtl5000_hifi),
};
@@ -812,7 +812,7 @@ static struct snd_soc_dai_link tegra_tlv320aic23_dai = {
.stream_name = "AIC23",
.dai_fmt = SND_SOC_DAIFMT_I2S |
SND_SOC_DAIFMT_NB_NF |
- SND_SOC_DAIFMT_CBS_CFS,
+ SND_SOC_DAIFMT_CBC_CFC,
SND_SOC_DAILINK_REG(tlv320aic23_hifi),
};
@@ -861,7 +861,7 @@ static struct snd_soc_dai_link tegra_rt5677_dai = {
.init = tegra_rt5677_init,
.dai_fmt = SND_SOC_DAIFMT_I2S |
SND_SOC_DAIFMT_NB_NF |
- SND_SOC_DAIFMT_CBS_CFS,
+ SND_SOC_DAIFMT_CBC_CFC,
SND_SOC_DAILINK_REG(rt5677_aif1),
};
@@ -895,7 +895,7 @@ static struct snd_soc_dai_link tegra_rt5640_dai = {
.init = tegra_asoc_machine_init,
.dai_fmt = SND_SOC_DAIFMT_I2S |
SND_SOC_DAIFMT_NB_NF |
- SND_SOC_DAIFMT_CBS_CFS,
+ SND_SOC_DAIFMT_CBC_CFC,
SND_SOC_DAILINK_REG(rt5640_aif1),
};
@@ -928,7 +928,7 @@ static struct snd_soc_dai_link tegra_rt5632_dai = {
.init = tegra_rt5677_init,
.dai_fmt = SND_SOC_DAIFMT_I2S |
SND_SOC_DAIFMT_NB_NF |
- SND_SOC_DAIFMT_CBS_CFS,
+ SND_SOC_DAIFMT_CBC_CFC,
SND_SOC_DAILINK_REG(rt5632_hifi),
};
@@ -961,7 +961,7 @@ static struct snd_soc_dai_link tegra_rt5631_dai = {
.init = tegra_asoc_machine_init,
.dai_fmt = SND_SOC_DAIFMT_I2S |
SND_SOC_DAIFMT_NB_NF |
- SND_SOC_DAIFMT_CBS_CFS,
+ SND_SOC_DAIFMT_CBC_CFC,
SND_SOC_DAILINK_REG(rt5631_hifi),
};
diff --git a/sound/soc/tegra/tegra_audio_graph_card.c b/sound/soc/tegra/tegra_audio_graph_card.c
index feba9d42bbc5..94b5ab77649b 100644
--- a/sound/soc/tegra/tegra_audio_graph_card.c
+++ b/sound/soc/tegra/tegra_audio_graph_card.c
@@ -1,8 +1,7 @@
// SPDX-License-Identifier: GPL-2.0-only
+// SPDX-FileCopyrightText: Copyright (c) 2020-2025 NVIDIA CORPORATION. All rights reserved.
//
// tegra_audio_graph_card.c - Audio Graph based Tegra Machine Driver
-//
-// Copyright (c) 2020-2021 NVIDIA CORPORATION. All rights reserved.
#include <linux/math64.h>
#include <linux/module.h>
@@ -232,11 +231,22 @@ static const struct tegra_audio_cdata tegra186_data = {
.plla_out0_rates[x11_RATE] = 45158400,
};
+static const struct tegra_audio_cdata tegra264_data = {
+ /* PLLA1 */
+ .plla_rates[x8_RATE] = 983040000,
+ .plla_rates[x11_RATE] = 993484800,
+ /* PLLA1_OUT1 */
+ .plla_out0_rates[x8_RATE] = 49152000,
+ .plla_out0_rates[x11_RATE] = 45158400,
+};
+
static const struct of_device_id graph_of_tegra_match[] = {
{ .compatible = "nvidia,tegra210-audio-graph-card",
.data = &tegra210_data },
{ .compatible = "nvidia,tegra186-audio-graph-card",
.data = &tegra186_data },
+ { .compatible = "nvidia,tegra264-audio-graph-card",
+ .data = &tegra264_data },
{},
};
MODULE_DEVICE_TABLE(of, graph_of_tegra_match);
@@ -248,7 +258,7 @@ static struct platform_driver tegra_audio_graph_card = {
.of_match_table = graph_of_tegra_match,
},
.probe = tegra_audio_graph_probe,
- .remove_new = simple_util_remove,
+ .remove = simple_util_remove,
};
module_platform_driver(tegra_audio_graph_card);
diff --git a/sound/soc/tegra/tegra_cif.h b/sound/soc/tegra/tegra_cif.h
index 7cca8068f4b5..916aa10d8af8 100644
--- a/sound/soc/tegra/tegra_cif.h
+++ b/sound/soc/tegra/tegra_cif.h
@@ -1,8 +1,7 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * tegra_cif.h - TEGRA Audio CIF Programming
+/* SPDX-License-Identifier: GPL-2.0-only
+ * SPDX-FileCopyrightText: Copyright (c) 2020-2025 NVIDIA CORPORATION. All rights reserved.
*
- * Copyright (c) 2020 NVIDIA CORPORATION. All rights reserved.
+ * tegra_cif.h - TEGRA Audio CIF Programming
*
*/
@@ -22,6 +21,10 @@
#define TEGRA_ACIF_CTRL_TRUNCATE_SHIFT 1
#define TEGRA_ACIF_CTRL_MONO_CONV_SHIFT 0
+#define TEGRA264_ACIF_CTRL_AUDIO_BITS_SHIFT 11
+#define TEGRA264_ACIF_CTRL_CLIENT_CH_SHIFT 14
+#define TEGRA264_ACIF_CTRL_AUDIO_CH_SHIFT 19
+
/* AUDIO/CLIENT_BITS values */
#define TEGRA_ACIF_BITS_8 1
#define TEGRA_ACIF_BITS_16 3
@@ -62,4 +65,23 @@ static inline void tegra_set_cif(struct regmap *regmap, unsigned int reg,
regmap_update_bits(regmap, reg, TEGRA_ACIF_UPDATE_MASK, value);
}
+static inline void tegra264_set_cif(struct regmap *regmap, unsigned int reg,
+ struct tegra_cif_conf *conf)
+{
+ unsigned int value;
+
+ value = (conf->threshold << TEGRA_ACIF_CTRL_FIFO_TH_SHIFT) |
+ ((conf->audio_ch - 1) << TEGRA264_ACIF_CTRL_AUDIO_CH_SHIFT) |
+ ((conf->client_ch - 1) << TEGRA264_ACIF_CTRL_CLIENT_CH_SHIFT) |
+ (conf->audio_bits << TEGRA264_ACIF_CTRL_AUDIO_BITS_SHIFT) |
+ (conf->client_bits << TEGRA_ACIF_CTRL_CLIENT_BITS_SHIFT) |
+ (conf->expand << TEGRA_ACIF_CTRL_EXPAND_SHIFT) |
+ (conf->stereo_conv << TEGRA_ACIF_CTRL_STEREO_CONV_SHIFT) |
+ (conf->replicate << TEGRA_ACIF_CTRL_REPLICATE_SHIFT) |
+ (conf->truncate << TEGRA_ACIF_CTRL_TRUNCATE_SHIFT) |
+ (conf->mono_conv << TEGRA_ACIF_CTRL_MONO_CONV_SHIFT);
+
+ regmap_update_bits(regmap, reg, TEGRA_ACIF_UPDATE_MASK, value);
+}
+
#endif
diff --git a/sound/soc/tegra/tegra_isomgr_bw.c b/sound/soc/tegra/tegra_isomgr_bw.c
new file mode 100644
index 000000000000..fa979960bc09
--- /dev/null
+++ b/sound/soc/tegra/tegra_isomgr_bw.c
@@ -0,0 +1,130 @@
+// SPDX-License-Identifier: GPL-2.0-only
+// SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES.
+// All rights reserved.
+//
+// ADMA bandwidth calculation
+
+#include <linux/interconnect.h>
+#include <linux/module.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include "tegra_isomgr_bw.h"
+#include "tegra210_admaif.h"
+
+#define MAX_SAMPLE_RATE 192 /* KHz*/
+#define MAX_BYTES_PER_SAMPLE 4
+
+int tegra_isomgr_adma_setbw(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai, bool is_running)
+{
+ struct device *dev = dai->dev;
+ struct tegra_admaif *admaif = snd_soc_dai_get_drvdata(dai);
+ struct tegra_adma_isomgr *adma_isomgr = admaif->adma_isomgr;
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct snd_pcm *pcm = substream->pcm;
+ u32 type = substream->stream, bandwidth = 0;
+ int sample_bytes;
+
+ if (!adma_isomgr)
+ return 0;
+
+ if (!runtime || !pcm)
+ return -EINVAL;
+
+ if (pcm->device >= adma_isomgr->max_pcm_device) {
+ dev_err(dev, "%s: PCM device number %d is greater than %d\n", __func__,
+ pcm->device, adma_isomgr->max_pcm_device);
+ return -EINVAL;
+ }
+
+ /*
+ * No action if stream is running and bandwidth is already set or
+ * stream is not running and bandwidth is already reset
+ */
+ if ((adma_isomgr->bw_per_dev[type][pcm->device] && is_running) ||
+ (!adma_isomgr->bw_per_dev[type][pcm->device] && !is_running))
+ return 0;
+
+ if (is_running) {
+ sample_bytes = snd_pcm_format_width(runtime->format) / 8;
+ if (sample_bytes < 0)
+ return sample_bytes;
+
+ /* KB/s kilo bytes per sec */
+ bandwidth = runtime->channels * (runtime->rate / 1000) *
+ sample_bytes;
+ }
+
+ mutex_lock(&adma_isomgr->mutex);
+
+ if (is_running) {
+ if (bandwidth + adma_isomgr->current_bandwidth > adma_isomgr->max_bw)
+ bandwidth = adma_isomgr->max_bw - adma_isomgr->current_bandwidth;
+
+ adma_isomgr->current_bandwidth += bandwidth;
+ } else {
+ adma_isomgr->current_bandwidth -= adma_isomgr->bw_per_dev[type][pcm->device];
+ }
+
+ mutex_unlock(&adma_isomgr->mutex);
+
+ adma_isomgr->bw_per_dev[type][pcm->device] = bandwidth;
+
+ dev_dbg(dev, "Setting up bandwidth to %d KBps\n", adma_isomgr->current_bandwidth);
+
+ return icc_set_bw(adma_isomgr->icc_path_handle,
+ adma_isomgr->current_bandwidth, adma_isomgr->max_bw);
+}
+
+int tegra_isomgr_adma_register(struct device *dev)
+{
+ struct tegra_admaif *admaif = dev_get_drvdata(dev);
+ struct tegra_adma_isomgr *adma_isomgr;
+ int i;
+
+ adma_isomgr = devm_kzalloc(dev, sizeof(struct tegra_adma_isomgr), GFP_KERNEL);
+ if (!adma_isomgr)
+ return -ENOMEM;
+
+ adma_isomgr->icc_path_handle = devm_of_icc_get(dev, "write");
+ if (IS_ERR(adma_isomgr->icc_path_handle))
+ return dev_err_probe(dev, PTR_ERR(adma_isomgr->icc_path_handle),
+ "failed to acquire interconnect path\n");
+
+ /* Either INTERCONNECT config OR interconnect property is not defined */
+ if (!adma_isomgr->icc_path_handle) {
+ devm_kfree(dev, adma_isomgr);
+ return 0;
+ }
+
+ adma_isomgr->max_pcm_device = admaif->soc_data->num_ch;
+ adma_isomgr->max_bw = STREAM_TYPE * MAX_SAMPLE_RATE * MAX_BYTES_PER_SAMPLE *
+ admaif->soc_data->max_stream_ch * adma_isomgr->max_pcm_device;
+
+ for (i = 0; i < STREAM_TYPE; i++) {
+ adma_isomgr->bw_per_dev[i] = devm_kzalloc(dev, adma_isomgr->max_pcm_device *
+ sizeof(u32), GFP_KERNEL);
+ if (!adma_isomgr->bw_per_dev[i])
+ return -ENOMEM;
+ }
+
+ adma_isomgr->current_bandwidth = 0;
+ mutex_init(&adma_isomgr->mutex);
+ admaif->adma_isomgr = adma_isomgr;
+
+ return 0;
+}
+
+void tegra_isomgr_adma_unregister(struct device *dev)
+{
+ struct tegra_admaif *admaif = dev_get_drvdata(dev);
+
+ if (!admaif->adma_isomgr)
+ return;
+
+ mutex_destroy(&admaif->adma_isomgr->mutex);
+}
+
+MODULE_AUTHOR("Mohan Kumar <mkumard@nvidia.com>");
+MODULE_DESCRIPTION("Tegra ADMA Bandwidth Request driver");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/tegra/tegra_isomgr_bw.h b/sound/soc/tegra/tegra_isomgr_bw.h
new file mode 100644
index 000000000000..86db3cfd4e43
--- /dev/null
+++ b/sound/soc/tegra/tegra_isomgr_bw.h
@@ -0,0 +1,31 @@
+/* SPDX-License-Identifier: GPL-2.0-only
+ * SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES.
+ * All rights reserved.
+ *
+ * tegra_isomgr_bw.h - Definitions for ADMA bandwidth calculation
+ *
+ */
+
+#ifndef __TEGRA_ISOMGR_BW_H__
+#define __TEGRA_ISOMGR_BW_H__
+
+/* Playback and Capture streams */
+#define STREAM_TYPE 2
+
+struct tegra_adma_isomgr {
+ /* Protect pcm devices bandwidth */
+ struct mutex mutex;
+ /* interconnect path handle */
+ struct icc_path *icc_path_handle;
+ u32 *bw_per_dev[STREAM_TYPE];
+ u32 current_bandwidth;
+ u32 max_pcm_device;
+ u32 max_bw;
+};
+
+int tegra_isomgr_adma_register(struct device *dev);
+void tegra_isomgr_adma_unregister(struct device *dev);
+int tegra_isomgr_adma_setbw(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai, bool is_running);
+
+#endif
diff --git a/sound/soc/tegra/tegra_pcm.c b/sound/soc/tegra/tegra_pcm.c
index 42acb56543db..05d59e03b1c5 100644
--- a/sound/soc/tegra/tegra_pcm.c
+++ b/sound/soc/tegra/tegra_pcm.c
@@ -76,7 +76,7 @@ EXPORT_SYMBOL_GPL(tegra_pcm_platform_unregister);
int tegra_pcm_open(struct snd_soc_component *component,
struct snd_pcm_substream *substream)
{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
struct snd_dmaengine_dai_dma_data *dmap;
struct dma_chan *chan;
struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0);
@@ -127,7 +127,7 @@ EXPORT_SYMBOL_GPL(tegra_pcm_open);
int tegra_pcm_close(struct snd_soc_component *component,
struct snd_pcm_substream *substream)
{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
if (rtd->dai_link->no_pcm)
return 0;
@@ -142,7 +142,7 @@ int tegra_pcm_hw_params(struct snd_soc_component *component,
struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params)
{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
struct snd_dmaengine_dai_dma_data *dmap;
struct dma_slave_config slave_config;
struct dma_chan *chan;
@@ -213,7 +213,7 @@ int tegra_pcm_construct(struct snd_soc_component *component,
* Fallback for backwards-compatibility with older device trees that
* have the iommus property in the virtual, top-level "sound" node.
*/
- if (!of_get_property(dev->of_node, "iommus", NULL))
+ if (!of_property_present(dev->of_node, "iommus"))
dev = rtd->card->snd_card->dev;
return tegra_pcm_dma_allocate(dev, rtd, tegra_pcm_hardware.buffer_bytes_max);
diff --git a/sound/soc/tegra/tegra_wm8903.c b/sound/soc/tegra/tegra_wm8903.c
index 6116d2e30fca..78b02c64d95c 100644
--- a/sound/soc/tegra/tegra_wm8903.c
+++ b/sound/soc/tegra/tegra_wm8903.c
@@ -124,7 +124,7 @@ static struct snd_soc_dai_link tegra_wm8903_dai = {
.init = tegra_wm8903_init,
.dai_fmt = SND_SOC_DAIFMT_I2S |
SND_SOC_DAIFMT_NB_NF |
- SND_SOC_DAIFMT_CBS_CFS,
+ SND_SOC_DAIFMT_CBC_CFC,
SND_SOC_DAILINK_REG(hifi),
};