summaryrefslogtreecommitdiff
path: root/sound/soc/tegra
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2021-04-30 22:48:14 +0300
committerLinus Torvalds <torvalds@linux-foundation.org>2021-04-30 22:48:14 +0300
commitb71428d7ab333a157216a1d73c8c82a178efada9 (patch)
tree94d268210d84948d5984f2fbe7d890c4aed1fabe /sound/soc/tegra
parent95275402f66e88c56144a2d859c13594b651b29b (diff)
parent2e6a731296be9d356fdccee9fb6ae345dad96438 (diff)
downloadlinux-b71428d7ab333a157216a1d73c8c82a178efada9.tar.xz
Merge tag 'sound-5.13-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound
Pull sound updates from Takashi Iwai: "No surprises in this development cycle, and most of work is about the fixes and the improvements of the existing code, while a new LED control layer and a few new drivers have been introduced. Here are some highlights: Core: - A common mute-LED framework was introduced. It is used by HD-audio for now, more adaption will follow later. The former "Mic Mute-LED Mode" mixer control has been replaced with the corresponding sysfs now. - User-control management was changed to count consumed bytes instead of capping by number of elements; this will allow more controls in the normal usage pattern while avoiding the possible memory exhaustion DoS ASoC: - Continued refactoring and cleanups in ASoC core and generic card drivers - Wide range of small cppcheck and warning fixes - New drivers for Freescale i.MX DMA over rpmsg, Mediatek MT6358 accessory detection, and Realtek RT1019, RT1316, RT711 and RT715 USB-audio: - Continued improvements and fixes of the implicit feedback mode, including better support for Pioneer and Roland/BOSS devices HD-audio: - Default back to non-buffer preallocation on x86 - Cirrus codec improvements, more quirks for Realtek codecs Others: - New virtio sound driver - FireWire Bebob updates" * tag 'sound-5.13-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound: (587 commits) ALSA: hda/conexant: Re-order CX5066 quirk table entries ALSA: hda/realtek: Remove redundant entry for ALC861 Haier/Uniwill devices ALSA: hda/realtek: Re-order ALC662 quirk table entries ALSA: hda/realtek: Re-order remaining ALC269 quirk table entries ALSA: hda/realtek: Re-order ALC269 Lenovo quirk table entries ALSA: hda/realtek: Re-order ALC269 Sony quirk table entries ALSA: hda/realtek: Re-order ALC269 ASUS quirk table entries ALSA: hda/realtek: Re-order ALC269 Dell quirk table entries ALSA: hda/realtek: Re-order ALC269 Acer quirk table entries ALSA: hda/realtek: Re-order ALC269 HP quirk table entries ALSA: hda/realtek: Re-order ALC882 Clevo quirk table entries ALSA: hda/realtek: Re-order ALC882 Sony quirk table entries ALSA: hda/realtek: Re-order ALC882 Acer quirk table entries ALSA: usb-audio: Remove redundant assignment to len ALSA: hda/realtek: Add quirk for Intel Clevo PCx0Dx ALSA: virtio: fix kernel-doc ALSA: hda/cirrus: Use CS8409 filter to fix abnormal sounds on Bullseye ALSA: hda/cirrus: Set Initial DMIC volume for Bullseye to -26 dB ALSA: sb: Fix two use after free in snd_sb_qsound_build ALSA: emu8000: Fix a use after free in snd_emu8000_create_mixer ...
Diffstat (limited to 'sound/soc/tegra')
-rw-r--r--sound/soc/tegra/tegra20_ac97.c21
-rw-r--r--sound/soc/tegra/tegra20_ac97.h1
-rw-r--r--sound/soc/tegra/tegra20_das.c8
-rw-r--r--sound/soc/tegra/tegra20_das.h6
-rw-r--r--sound/soc/tegra/tegra20_i2s.c64
-rw-r--r--sound/soc/tegra/tegra20_i2s.h1
-rw-r--r--sound/soc/tegra/tegra20_spdif.c20
-rw-r--r--sound/soc/tegra/tegra30_ahub.c172
-rw-r--r--sound/soc/tegra/tegra30_ahub.h5
-rw-r--r--sound/soc/tegra/tegra30_i2s.c69
-rw-r--r--sound/soc/tegra/tegra_audio_graph_card.c5
11 files changed, 155 insertions, 217 deletions
diff --git a/sound/soc/tegra/tegra20_ac97.c b/sound/soc/tegra/tegra20_ac97.c
index 06c728ae17ed..c454a34c15c4 100644
--- a/sound/soc/tegra/tegra20_ac97.c
+++ b/sound/soc/tegra/tegra20_ac97.c
@@ -21,6 +21,7 @@
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/regmap.h>
+#include <linux/reset.h>
#include <linux/slab.h>
#include <sound/core.h>
#include <sound/pcm.h>
@@ -313,6 +314,12 @@ static int tegra20_ac97_platform_probe(struct platform_device *pdev)
}
dev_set_drvdata(&pdev->dev, ac97);
+ ac97->reset = devm_reset_control_get_exclusive(&pdev->dev, "ac97");
+ if (IS_ERR(ac97->reset)) {
+ dev_err(&pdev->dev, "Can't retrieve ac97 reset\n");
+ return PTR_ERR(ac97->reset);
+ }
+
ac97->clk_ac97 = devm_clk_get(&pdev->dev, NULL);
if (IS_ERR(ac97->clk_ac97)) {
dev_err(&pdev->dev, "Can't retrieve ac97 clock\n");
@@ -364,12 +371,26 @@ static int tegra20_ac97_platform_probe(struct platform_device *pdev)
ac97->playback_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
ac97->playback_dma_data.maxburst = 4;
+ ret = reset_control_assert(ac97->reset);
+ if (ret) {
+ dev_err(&pdev->dev, "Failed to assert AC'97 reset: %d\n", ret);
+ goto err_clk_put;
+ }
+
ret = clk_prepare_enable(ac97->clk_ac97);
if (ret) {
dev_err(&pdev->dev, "clk_enable failed: %d\n", ret);
goto err_clk_put;
}
+ usleep_range(10, 100);
+
+ ret = reset_control_deassert(ac97->reset);
+ if (ret) {
+ dev_err(&pdev->dev, "Failed to deassert AC'97 reset: %d\n", ret);
+ goto err_clk_disable_unprepare;
+ }
+
ret = snd_soc_set_ac97_ops(&tegra20_ac97_ops);
if (ret) {
dev_err(&pdev->dev, "Failed to set AC'97 ops: %d\n", ret);
diff --git a/sound/soc/tegra/tegra20_ac97.h b/sound/soc/tegra/tegra20_ac97.h
index e467cd1ff2ca..870ea09ff301 100644
--- a/sound/soc/tegra/tegra20_ac97.h
+++ b/sound/soc/tegra/tegra20_ac97.h
@@ -78,6 +78,7 @@ struct tegra20_ac97 {
struct clk *clk_ac97;
struct snd_dmaengine_dai_dma_data capture_dma_data;
struct snd_dmaengine_dai_dma_data playback_dma_data;
+ struct reset_control *reset;
struct regmap *regmap;
int reset_gpio;
int sync_gpio;
diff --git a/sound/soc/tegra/tegra20_das.c b/sound/soc/tegra/tegra20_das.c
index 79dba878d854..69c651274c12 100644
--- a/sound/soc/tegra/tegra20_das.c
+++ b/sound/soc/tegra/tegra20_das.c
@@ -61,10 +61,10 @@ int tegra20_das_connect_dap_to_dap(int dap, int otherdap, int master,
addr = TEGRA20_DAS_DAP_CTRL_SEL +
(dap * TEGRA20_DAS_DAP_CTRL_SEL_STRIDE);
- reg = otherdap << TEGRA20_DAS_DAP_CTRL_SEL_DAP_CTRL_SEL_P |
- !!sdata2rx << TEGRA20_DAS_DAP_CTRL_SEL_DAP_SDATA2_TX_RX_P |
- !!sdata1rx << TEGRA20_DAS_DAP_CTRL_SEL_DAP_SDATA1_TX_RX_P |
- !!master << TEGRA20_DAS_DAP_CTRL_SEL_DAP_MS_SEL_P;
+ reg = (otherdap << TEGRA20_DAS_DAP_CTRL_SEL_DAP_CTRL_SEL_P) |
+ (!!sdata2rx << TEGRA20_DAS_DAP_CTRL_SEL_DAP_SDATA2_TX_RX_P) |
+ (!!sdata1rx << TEGRA20_DAS_DAP_CTRL_SEL_DAP_SDATA1_TX_RX_P) |
+ (!!master << TEGRA20_DAS_DAP_CTRL_SEL_DAP_MS_SEL_P);
tegra20_das_write(addr, reg);
diff --git a/sound/soc/tegra/tegra20_das.h b/sound/soc/tegra/tegra20_das.h
index d22abc4d08e6..18e832ded73a 100644
--- a/sound/soc/tegra/tegra20_das.h
+++ b/sound/soc/tegra/tegra20_das.h
@@ -95,7 +95,7 @@ struct tegra20_das {
* dap_id: DAP to connect: TEGRA20_DAS_DAP_ID_*
* dac_sel: DAC to connect to: TEGRA20_DAS_DAP_SEL_DAC*
*/
-extern int tegra20_das_connect_dap_to_dac(int dap_id, int dac_sel);
+extern int tegra20_das_connect_dap_to_dac(int dap, int dac);
/*
* Connect a DAP to another DAP
@@ -105,7 +105,7 @@ extern int tegra20_das_connect_dap_to_dac(int dap_id, int dac_sel);
* sdata1rx: Is this DAP's SDATA1 pin RX (1) or TX (0)
* sdata2rx: Is this DAP's SDATA2 pin RX (1) or TX (0)
*/
-extern int tegra20_das_connect_dap_to_dap(int dap_id, int other_dap_sel,
+extern int tegra20_das_connect_dap_to_dap(int dap, int otherdap,
int master, int sdata1rx,
int sdata2rx);
@@ -115,6 +115,6 @@ extern int tegra20_das_connect_dap_to_dap(int dap_id, int other_dap_sel,
* dac_id: DAC ID to connect: TEGRA20_DAS_DAC_ID_*
* dap_sel: DAP to receive input from: TEGRA20_DAS_DAC_SEL_DAP*
*/
-extern int tegra20_das_connect_dac_to_dap(int dac_id, int dap_sel);
+extern int tegra20_das_connect_dac_to_dap(int dac, int dap);
#endif
diff --git a/sound/soc/tegra/tegra20_i2s.c b/sound/soc/tegra/tegra20_i2s.c
index d7a3d046c8f8..b280ebd72591 100644
--- a/sound/soc/tegra/tegra20_i2s.c
+++ b/sound/soc/tegra/tegra20_i2s.c
@@ -22,6 +22,7 @@
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/regmap.h>
+#include <linux/reset.h>
#include <linux/slab.h>
#include <sound/core.h>
#include <sound/pcm.h>
@@ -33,27 +34,51 @@
#define DRV_NAME "tegra20-i2s"
-static int tegra20_i2s_runtime_suspend(struct device *dev)
+static __maybe_unused int tegra20_i2s_runtime_suspend(struct device *dev)
{
struct tegra20_i2s *i2s = dev_get_drvdata(dev);
+ regcache_cache_only(i2s->regmap, true);
+
clk_disable_unprepare(i2s->clk_i2s);
return 0;
}
-static int tegra20_i2s_runtime_resume(struct device *dev)
+static __maybe_unused int tegra20_i2s_runtime_resume(struct device *dev)
{
struct tegra20_i2s *i2s = dev_get_drvdata(dev);
int ret;
+ ret = reset_control_assert(i2s->reset);
+ if (ret)
+ return ret;
+
ret = clk_prepare_enable(i2s->clk_i2s);
if (ret) {
dev_err(dev, "clk_enable failed: %d\n", ret);
return ret;
}
+ usleep_range(10, 100);
+
+ ret = reset_control_deassert(i2s->reset);
+ if (ret)
+ goto disable_clocks;
+
+ regcache_cache_only(i2s->regmap, false);
+ regcache_mark_dirty(i2s->regmap);
+
+ ret = regcache_sync(i2s->regmap);
+ if (ret)
+ goto disable_clocks;
+
return 0;
+
+disable_clocks:
+ clk_disable_unprepare(i2s->clk_i2s);
+
+ return ret;
}
static int tegra20_i2s_set_fmt(struct snd_soc_dai *dai,
@@ -339,7 +364,13 @@ static int tegra20_i2s_platform_probe(struct platform_device *pdev)
i2s->dai = tegra20_i2s_dai_template;
i2s->dai.name = dev_name(&pdev->dev);
- i2s->clk_i2s = clk_get(&pdev->dev, NULL);
+ i2s->reset = devm_reset_control_get_exclusive(&pdev->dev, "i2s");
+ if (IS_ERR(i2s->reset)) {
+ dev_err(&pdev->dev, "Can't retrieve i2s reset\n");
+ return PTR_ERR(i2s->reset);
+ }
+
+ i2s->clk_i2s = devm_clk_get(&pdev->dev, NULL);
if (IS_ERR(i2s->clk_i2s)) {
dev_err(&pdev->dev, "Can't retrieve i2s clock\n");
ret = PTR_ERR(i2s->clk_i2s);
@@ -350,7 +381,7 @@ static int tegra20_i2s_platform_probe(struct platform_device *pdev)
regs = devm_ioremap_resource(&pdev->dev, mem);
if (IS_ERR(regs)) {
ret = PTR_ERR(regs);
- goto err_clk_put;
+ goto err;
}
i2s->regmap = devm_regmap_init_mmio(&pdev->dev, regs,
@@ -358,7 +389,7 @@ static int tegra20_i2s_platform_probe(struct platform_device *pdev)
if (IS_ERR(i2s->regmap)) {
dev_err(&pdev->dev, "regmap init failed\n");
ret = PTR_ERR(i2s->regmap);
- goto err_clk_put;
+ goto err;
}
i2s->capture_dma_data.addr = mem->start + TEGRA20_I2S_FIFO2;
@@ -370,18 +401,13 @@ static int tegra20_i2s_platform_probe(struct platform_device *pdev)
i2s->playback_dma_data.maxburst = 4;
pm_runtime_enable(&pdev->dev);
- if (!pm_runtime_enabled(&pdev->dev)) {
- ret = tegra20_i2s_runtime_resume(&pdev->dev);
- if (ret)
- goto err_pm_disable;
- }
ret = snd_soc_register_component(&pdev->dev, &tegra20_i2s_component,
&i2s->dai, 1);
if (ret) {
dev_err(&pdev->dev, "Could not register DAI: %d\n", ret);
ret = -ENOMEM;
- goto err_suspend;
+ goto err_pm_disable;
}
ret = tegra_pcm_platform_register(&pdev->dev);
@@ -394,29 +420,17 @@ static int tegra20_i2s_platform_probe(struct platform_device *pdev)
err_unregister_component:
snd_soc_unregister_component(&pdev->dev);
-err_suspend:
- if (!pm_runtime_status_suspended(&pdev->dev))
- tegra20_i2s_runtime_suspend(&pdev->dev);
err_pm_disable:
pm_runtime_disable(&pdev->dev);
-err_clk_put:
- clk_put(i2s->clk_i2s);
err:
return ret;
}
static int tegra20_i2s_platform_remove(struct platform_device *pdev)
{
- struct tegra20_i2s *i2s = dev_get_drvdata(&pdev->dev);
-
- pm_runtime_disable(&pdev->dev);
- if (!pm_runtime_status_suspended(&pdev->dev))
- tegra20_i2s_runtime_suspend(&pdev->dev);
-
tegra_pcm_platform_unregister(&pdev->dev);
snd_soc_unregister_component(&pdev->dev);
-
- clk_put(i2s->clk_i2s);
+ pm_runtime_disable(&pdev->dev);
return 0;
}
@@ -429,6 +443,8 @@ 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)
};
static struct platform_driver tegra20_i2s_driver = {
diff --git a/sound/soc/tegra/tegra20_i2s.h b/sound/soc/tegra/tegra20_i2s.h
index 628d3ca09f42..8233e5fa2eff 100644
--- a/sound/soc/tegra/tegra20_i2s.h
+++ b/sound/soc/tegra/tegra20_i2s.h
@@ -144,6 +144,7 @@ struct tegra20_i2s {
struct snd_dmaengine_dai_dma_data capture_dma_data;
struct snd_dmaengine_dai_dma_data playback_dma_data;
struct regmap *regmap;
+ struct reset_control *reset;
};
#endif
diff --git a/sound/soc/tegra/tegra20_spdif.c b/sound/soc/tegra/tegra20_spdif.c
index 5839833e23a0..de698ff2a69c 100644
--- a/sound/soc/tegra/tegra20_spdif.c
+++ b/sound/soc/tegra/tegra20_spdif.c
@@ -24,7 +24,7 @@
#define DRV_NAME "tegra20-spdif"
-static int tegra20_spdif_runtime_suspend(struct device *dev)
+static __maybe_unused int tegra20_spdif_runtime_suspend(struct device *dev)
{
struct tegra20_spdif *spdif = dev_get_drvdata(dev);
@@ -33,7 +33,7 @@ static int tegra20_spdif_runtime_suspend(struct device *dev)
return 0;
}
-static int tegra20_spdif_runtime_resume(struct device *dev)
+static __maybe_unused int tegra20_spdif_runtime_resume(struct device *dev)
{
struct tegra20_spdif *spdif = dev_get_drvdata(dev);
int ret;
@@ -294,18 +294,13 @@ static int tegra20_spdif_platform_probe(struct platform_device *pdev)
spdif->playback_dma_data.slave_id = dmareq->start;
pm_runtime_enable(&pdev->dev);
- if (!pm_runtime_enabled(&pdev->dev)) {
- ret = tegra20_spdif_runtime_resume(&pdev->dev);
- if (ret)
- goto err_pm_disable;
- }
ret = snd_soc_register_component(&pdev->dev, &tegra20_spdif_component,
&tegra20_spdif_dai, 1);
if (ret) {
dev_err(&pdev->dev, "Could not register DAI: %d\n", ret);
ret = -ENOMEM;
- goto err_suspend;
+ goto err_pm_disable;
}
ret = tegra_pcm_platform_register(&pdev->dev);
@@ -318,9 +313,6 @@ static int tegra20_spdif_platform_probe(struct platform_device *pdev)
err_unregister_component:
snd_soc_unregister_component(&pdev->dev);
-err_suspend:
- if (!pm_runtime_status_suspended(&pdev->dev))
- tegra20_spdif_runtime_suspend(&pdev->dev);
err_pm_disable:
pm_runtime_disable(&pdev->dev);
@@ -329,13 +321,11 @@ err_pm_disable:
static int tegra20_spdif_platform_remove(struct platform_device *pdev)
{
- pm_runtime_disable(&pdev->dev);
- if (!pm_runtime_status_suspended(&pdev->dev))
- tegra20_spdif_runtime_suspend(&pdev->dev);
-
tegra_pcm_platform_unregister(&pdev->dev);
snd_soc_unregister_component(&pdev->dev);
+ pm_runtime_disable(&pdev->dev);
+
return 0;
}
diff --git a/sound/soc/tegra/tegra30_ahub.c b/sound/soc/tegra/tegra30_ahub.c
index 9ef05ca4f6c4..4692c70ed933 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 int tegra30_ahub_runtime_suspend(struct device *dev)
+static __maybe_unused int tegra30_ahub_runtime_suspend(struct device *dev)
{
regcache_cache_only(ahub->regmap_apbif, true);
regcache_cache_only(ahub->regmap_ahub, true);
@@ -61,11 +61,11 @@ static int tegra30_ahub_runtime_suspend(struct device *dev)
* stopping streams should dynamically adjust the clock as required. However,
* this is not yet implemented.
*/
-static int tegra30_ahub_runtime_resume(struct device *dev)
+static __maybe_unused int tegra30_ahub_runtime_resume(struct device *dev)
{
int ret;
- ret = reset_control_assert(ahub->reset);
+ ret = reset_control_bulk_assert(ahub->nresets, ahub->resets);
if (ret)
return ret;
@@ -75,7 +75,7 @@ static int tegra30_ahub_runtime_resume(struct device *dev)
usleep_range(10, 100);
- ret = reset_control_deassert(ahub->reset);
+ ret = reset_control_bulk_deassert(ahub->nresets, ahub->resets);
if (ret)
goto disable_clocks;
@@ -339,41 +339,28 @@ int tegra30_ahub_unset_rx_cif_source(enum tegra30_ahub_rxcif rxcif)
}
EXPORT_SYMBOL_GPL(tegra30_ahub_unset_rx_cif_source);
-#define MOD_LIST_MASK_TEGRA30 BIT(0)
-#define MOD_LIST_MASK_TEGRA114 BIT(1)
-#define MOD_LIST_MASK_TEGRA124 BIT(2)
-
-#define MOD_LIST_MASK_TEGRA30_OR_LATER \
- (MOD_LIST_MASK_TEGRA30 | MOD_LIST_MASK_TEGRA114 | \
- MOD_LIST_MASK_TEGRA124)
-#define MOD_LIST_MASK_TEGRA114_OR_LATER \
- (MOD_LIST_MASK_TEGRA114 | MOD_LIST_MASK_TEGRA124)
-
-static const struct {
- const char *rst_name;
- u32 mod_list_mask;
-} configlink_mods[] = {
- { "d_audio", MOD_LIST_MASK_TEGRA30_OR_LATER },
- { "apbif", MOD_LIST_MASK_TEGRA30_OR_LATER },
- { "i2s0", MOD_LIST_MASK_TEGRA30_OR_LATER },
- { "i2s1", MOD_LIST_MASK_TEGRA30_OR_LATER },
- { "i2s2", MOD_LIST_MASK_TEGRA30_OR_LATER },
- { "i2s3", MOD_LIST_MASK_TEGRA30_OR_LATER },
- { "i2s4", MOD_LIST_MASK_TEGRA30_OR_LATER },
- { "dam0", MOD_LIST_MASK_TEGRA30_OR_LATER },
- { "dam1", MOD_LIST_MASK_TEGRA30_OR_LATER },
- { "dam2", MOD_LIST_MASK_TEGRA30_OR_LATER },
- { "spdif", MOD_LIST_MASK_TEGRA30_OR_LATER },
- { "amx", MOD_LIST_MASK_TEGRA114_OR_LATER },
- { "adx", MOD_LIST_MASK_TEGRA114_OR_LATER },
- { "amx1", MOD_LIST_MASK_TEGRA124 },
- { "adx1", MOD_LIST_MASK_TEGRA124 },
- { "afc0", MOD_LIST_MASK_TEGRA124 },
- { "afc1", MOD_LIST_MASK_TEGRA124 },
- { "afc2", MOD_LIST_MASK_TEGRA124 },
- { "afc3", MOD_LIST_MASK_TEGRA124 },
- { "afc4", MOD_LIST_MASK_TEGRA124 },
- { "afc5", MOD_LIST_MASK_TEGRA124 },
+static const struct reset_control_bulk_data tegra30_ahub_resets_data[] = {
+ { "d_audio" },
+ { "apbif" },
+ { "i2s0" },
+ { "i2s1" },
+ { "i2s2" },
+ { "i2s3" },
+ { "i2s4" },
+ { "dam0" },
+ { "dam1" },
+ { "dam2" },
+ { "spdif" },
+ { "amx" }, /* Tegra114+ */
+ { "adx" }, /* Tegra114+ */
+ { "amx1" }, /* Tegra124 */
+ { "adx1" }, /* Tegra124 */
+ { "afc0" }, /* Tegra124 */
+ { "afc1" }, /* Tegra124 */
+ { "afc2" }, /* Tegra124 */
+ { "afc3" }, /* Tegra124 */
+ { "afc4" }, /* Tegra124 */
+ { "afc5" }, /* Tegra124 */
};
#define LAST_REG(name) \
@@ -502,17 +489,17 @@ static const struct regmap_config tegra30_ahub_ahub_regmap_config = {
};
static struct tegra30_ahub_soc_data soc_data_tegra30 = {
- .mod_list_mask = MOD_LIST_MASK_TEGRA30,
+ .num_resets = 11,
.set_audio_cif = tegra30_ahub_set_cif,
};
static struct tegra30_ahub_soc_data soc_data_tegra114 = {
- .mod_list_mask = MOD_LIST_MASK_TEGRA114,
+ .num_resets = 13,
.set_audio_cif = tegra30_ahub_set_cif,
};
static struct tegra30_ahub_soc_data soc_data_tegra124 = {
- .mod_list_mask = MOD_LIST_MASK_TEGRA124,
+ .num_resets = 21,
.set_audio_cif = tegra124_ahub_set_cif,
};
@@ -527,48 +514,25 @@ static int tegra30_ahub_probe(struct platform_device *pdev)
{
const struct of_device_id *match;
const struct tegra30_ahub_soc_data *soc_data;
- struct reset_control *rst;
- int i;
struct resource *res0;
void __iomem *regs_apbif, *regs_ahub;
int ret = 0;
- if (ahub)
- return -ENODEV;
-
match = of_match_device(tegra30_ahub_of_match, &pdev->dev);
if (!match)
return -EINVAL;
soc_data = match->data;
- /*
- * The AHUB hosts a register bus: the "configlink". For this to
- * operate correctly, all devices on this bus must be out of reset.
- */
- for (i = 0; i < ARRAY_SIZE(configlink_mods); i++) {
- if (!(configlink_mods[i].mod_list_mask &
- soc_data->mod_list_mask))
- continue;
-
- rst = reset_control_get_exclusive(&pdev->dev,
- configlink_mods[i].rst_name);
- if (IS_ERR(rst)) {
- dev_err(&pdev->dev, "Can't get reset %s\n",
- configlink_mods[i].rst_name);
- ret = PTR_ERR(rst);
- return ret;
- }
-
- /* just check presence of the reset control in DT */
- reset_control_put(rst);
- }
-
ahub = devm_kzalloc(&pdev->dev, sizeof(struct tegra30_ahub),
GFP_KERNEL);
if (!ahub)
return -ENOMEM;
dev_set_drvdata(&pdev->dev, ahub);
+ BUILD_BUG_ON(sizeof(ahub->resets) != sizeof(tegra30_ahub_resets_data));
+ memcpy(ahub->resets, tegra30_ahub_resets_data, sizeof(ahub->resets));
+
+ ahub->nresets = soc_data->num_resets;
ahub->soc_data = soc_data;
ahub->dev = &pdev->dev;
@@ -577,18 +541,21 @@ static int tegra30_ahub_probe(struct platform_device *pdev)
ret = devm_clk_bulk_get(&pdev->dev, ahub->nclocks, ahub->clocks);
if (ret)
- return ret;
+ goto err_unset_ahub;
- ahub->reset = devm_reset_control_array_get_exclusive(&pdev->dev);
- if (IS_ERR(ahub->reset)) {
- dev_err(&pdev->dev, "Can't get resets: %pe\n", ahub->reset);
- return PTR_ERR(ahub->reset);
+ ret = devm_reset_control_bulk_get_exclusive(&pdev->dev, ahub->nresets,
+ ahub->resets);
+ if (ret) {
+ dev_err(&pdev->dev, "Can't get resets: %d\n", ret);
+ goto err_unset_ahub;
}
res0 = platform_get_resource(pdev, IORESOURCE_MEM, 0);
regs_apbif = devm_ioremap_resource(&pdev->dev, res0);
- if (IS_ERR(regs_apbif))
- return PTR_ERR(regs_apbif);
+ if (IS_ERR(regs_apbif)) {
+ ret = PTR_ERR(regs_apbif);
+ goto err_unset_ahub;
+ }
ahub->apbif_addr = res0->start;
@@ -597,82 +564,51 @@ static int tegra30_ahub_probe(struct platform_device *pdev)
if (IS_ERR(ahub->regmap_apbif)) {
dev_err(&pdev->dev, "apbif regmap init failed\n");
ret = PTR_ERR(ahub->regmap_apbif);
- return ret;
+ goto err_unset_ahub;
}
regcache_cache_only(ahub->regmap_apbif, true);
regs_ahub = devm_platform_ioremap_resource(pdev, 1);
- if (IS_ERR(regs_ahub))
- return PTR_ERR(regs_ahub);
+ if (IS_ERR(regs_ahub)) {
+ ret = PTR_ERR(regs_ahub);
+ goto err_unset_ahub;
+ }
ahub->regmap_ahub = devm_regmap_init_mmio(&pdev->dev, regs_ahub,
&tegra30_ahub_ahub_regmap_config);
if (IS_ERR(ahub->regmap_ahub)) {
dev_err(&pdev->dev, "ahub regmap init failed\n");
ret = PTR_ERR(ahub->regmap_ahub);
- return ret;
+ goto err_unset_ahub;
}
regcache_cache_only(ahub->regmap_ahub, true);
pm_runtime_enable(&pdev->dev);
- if (!pm_runtime_enabled(&pdev->dev)) {
- ret = tegra30_ahub_runtime_resume(&pdev->dev);
- if (ret)
- goto err_pm_disable;
- }
of_platform_populate(pdev->dev.of_node, NULL, NULL, &pdev->dev);
return 0;
-err_pm_disable:
- pm_runtime_disable(&pdev->dev);
+err_unset_ahub:
+ ahub = NULL;
return ret;
}
static int tegra30_ahub_remove(struct platform_device *pdev)
{
- if (!ahub)
- return -ENODEV;
-
pm_runtime_disable(&pdev->dev);
- if (!pm_runtime_status_suspended(&pdev->dev))
- tegra30_ahub_runtime_suspend(&pdev->dev);
- return 0;
-}
-
-#ifdef CONFIG_PM_SLEEP
-static int tegra30_ahub_suspend(struct device *dev)
-{
- regcache_mark_dirty(ahub->regmap_ahub);
- regcache_mark_dirty(ahub->regmap_apbif);
+ ahub = NULL;
return 0;
}
-static int tegra30_ahub_resume(struct device *dev)
-{
- int ret;
-
- ret = pm_runtime_get_sync(dev);
- if (ret < 0) {
- pm_runtime_put(dev);
- return ret;
- }
- ret = regcache_sync(ahub->regmap_ahub);
- ret |= regcache_sync(ahub->regmap_apbif);
- pm_runtime_put(dev);
-
- return ret;
-}
-#endif
-
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(tegra30_ahub_suspend, tegra30_ahub_resume)
+ SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
+ pm_runtime_force_resume)
};
static struct platform_driver tegra30_ahub_driver = {
diff --git a/sound/soc/tegra/tegra30_ahub.h b/sound/soc/tegra/tegra30_ahub.h
index 3b85244f87f1..c9eaf4ec8f6e 100644
--- a/sound/soc/tegra/tegra30_ahub.h
+++ b/sound/soc/tegra/tegra30_ahub.h
@@ -491,7 +491,7 @@ void tegra124_ahub_set_cif(struct regmap *regmap, unsigned int reg,
struct tegra30_ahub_cif_conf *conf);
struct tegra30_ahub_soc_data {
- u32 mod_list_mask;
+ unsigned int num_resets;
void (*set_audio_cif)(struct regmap *regmap,
unsigned int reg,
struct tegra30_ahub_cif_conf *conf);
@@ -511,7 +511,8 @@ struct tegra30_ahub_soc_data {
struct tegra30_ahub {
const struct tegra30_ahub_soc_data *soc_data;
struct device *dev;
- struct reset_control *reset;
+ struct reset_control_bulk_data resets[21];
+ unsigned int nresets;
struct clk_bulk_data clocks[2];
unsigned int nclocks;
resource_size_t apbif_addr;
diff --git a/sound/soc/tegra/tegra30_i2s.c b/sound/soc/tegra/tegra30_i2s.c
index 6740df541508..36344f0a64c1 100644
--- a/sound/soc/tegra/tegra30_i2s.c
+++ b/sound/soc/tegra/tegra30_i2s.c
@@ -23,6 +23,7 @@
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/regmap.h>
+#include <linux/reset.h>
#include <linux/slab.h>
#include <sound/core.h>
#include <sound/pcm.h>
@@ -35,7 +36,7 @@
#define DRV_NAME "tegra30-i2s"
-static int tegra30_i2s_runtime_suspend(struct device *dev)
+static __maybe_unused int tegra30_i2s_runtime_suspend(struct device *dev)
{
struct tegra30_i2s *i2s = dev_get_drvdata(dev);
@@ -46,7 +47,7 @@ static int tegra30_i2s_runtime_suspend(struct device *dev)
return 0;
}
-static int tegra30_i2s_runtime_resume(struct device *dev)
+static __maybe_unused int tegra30_i2s_runtime_resume(struct device *dev)
{
struct tegra30_i2s *i2s = dev_get_drvdata(dev);
int ret;
@@ -58,8 +59,18 @@ static int tegra30_i2s_runtime_resume(struct device *dev)
}
regcache_cache_only(i2s->regmap, false);
+ regcache_mark_dirty(i2s->regmap);
+
+ ret = regcache_sync(i2s->regmap);
+ if (ret)
+ goto disable_clocks;
return 0;
+
+disable_clocks:
+ clk_disable_unprepare(i2s->clk_i2s);
+
+ return ret;
}
static int tegra30_i2s_set_fmt(struct snd_soc_dai *dai,
@@ -427,7 +438,7 @@ static int tegra30_i2s_platform_probe(struct platform_device *pdev)
i2s->playback_i2s_cif = cif_ids[0];
i2s->capture_i2s_cif = cif_ids[1];
- i2s->clk_i2s = clk_get(&pdev->dev, NULL);
+ i2s->clk_i2s = devm_clk_get(&pdev->dev, NULL);
if (IS_ERR(i2s->clk_i2s)) {
dev_err(&pdev->dev, "Can't retrieve i2s clock\n");
ret = PTR_ERR(i2s->clk_i2s);
@@ -437,7 +448,7 @@ static int tegra30_i2s_platform_probe(struct platform_device *pdev)
regs = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(regs)) {
ret = PTR_ERR(regs);
- goto err_clk_put;
+ goto err;
}
i2s->regmap = devm_regmap_init_mmio(&pdev->dev, regs,
@@ -445,16 +456,11 @@ static int tegra30_i2s_platform_probe(struct platform_device *pdev)
if (IS_ERR(i2s->regmap)) {
dev_err(&pdev->dev, "regmap init failed\n");
ret = PTR_ERR(i2s->regmap);
- goto err_clk_put;
+ goto err;
}
regcache_cache_only(i2s->regmap, true);
pm_runtime_enable(&pdev->dev);
- if (!pm_runtime_enabled(&pdev->dev)) {
- ret = tegra30_i2s_runtime_resume(&pdev->dev);
- if (ret)
- goto err_pm_disable;
- }
i2s->playback_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
i2s->playback_dma_data.maxburst = 4;
@@ -464,7 +470,7 @@ static int tegra30_i2s_platform_probe(struct platform_device *pdev)
&i2s->playback_dma_data.addr);
if (ret) {
dev_err(&pdev->dev, "Could not alloc TX FIFO: %d\n", ret);
- goto err_suspend;
+ goto err_pm_disable;
}
ret = tegra30_ahub_set_rx_cif_source(i2s->playback_i2s_cif,
i2s->playback_fifo_cif);
@@ -518,13 +524,8 @@ err_unroute_tx_fifo:
tegra30_ahub_unset_rx_cif_source(i2s->playback_i2s_cif);
err_free_tx_fifo:
tegra30_ahub_free_tx_fifo(i2s->playback_fifo_cif);
-err_suspend:
- if (!pm_runtime_status_suspended(&pdev->dev))
- tegra30_i2s_runtime_suspend(&pdev->dev);
err_pm_disable:
pm_runtime_disable(&pdev->dev);
-err_clk_put:
- clk_put(i2s->clk_i2s);
err:
return ret;
}
@@ -533,10 +534,6 @@ static int tegra30_i2s_platform_remove(struct platform_device *pdev)
{
struct tegra30_i2s *i2s = dev_get_drvdata(&pdev->dev);
- pm_runtime_disable(&pdev->dev);
- if (!pm_runtime_status_suspended(&pdev->dev))
- tegra30_i2s_runtime_suspend(&pdev->dev);
-
tegra_pcm_platform_unregister(&pdev->dev);
snd_soc_unregister_component(&pdev->dev);
@@ -546,42 +543,16 @@ static int tegra30_i2s_platform_remove(struct platform_device *pdev)
tegra30_ahub_unset_rx_cif_source(i2s->playback_i2s_cif);
tegra30_ahub_free_tx_fifo(i2s->playback_fifo_cif);
- clk_put(i2s->clk_i2s);
-
- return 0;
-}
-
-#ifdef CONFIG_PM_SLEEP
-static int tegra30_i2s_suspend(struct device *dev)
-{
- struct tegra30_i2s *i2s = dev_get_drvdata(dev);
-
- regcache_mark_dirty(i2s->regmap);
+ pm_runtime_disable(&pdev->dev);
return 0;
}
-static int tegra30_i2s_resume(struct device *dev)
-{
- struct tegra30_i2s *i2s = dev_get_drvdata(dev);
- int ret;
-
- ret = pm_runtime_get_sync(dev);
- if (ret < 0) {
- pm_runtime_put(dev);
- return ret;
- }
- ret = regcache_sync(i2s->regmap);
- pm_runtime_put(dev);
-
- return ret;
-}
-#endif
-
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(tegra30_i2s_suspend, tegra30_i2s_resume)
+ SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
+ pm_runtime_force_resume)
};
static struct platform_driver tegra30_i2s_driver = {
diff --git a/sound/soc/tegra/tegra_audio_graph_card.c b/sound/soc/tegra/tegra_audio_graph_card.c
index ddedf18adde1..1f2c5018bf5a 100644
--- a/sound/soc/tegra/tegra_audio_graph_card.c
+++ b/sound/soc/tegra/tegra_audio_graph_card.c
@@ -184,7 +184,7 @@ static int tegra_audio_graph_card_probe(struct snd_soc_card *card)
return PTR_ERR(priv->clk_plla_out0);
}
- return audio_graph_card_probe(card);
+ return asoc_graph_card_probe(card);
}
static int tegra_audio_graph_probe(struct platform_device *pdev)
@@ -198,6 +198,7 @@ static int tegra_audio_graph_probe(struct platform_device *pdev)
return -ENOMEM;
card = simple_priv_to_card(&priv->simple);
+ card->driver_name = "tegra-ape";
card->probe = tegra_audio_graph_card_probe;
@@ -243,7 +244,7 @@ static struct platform_driver tegra_audio_graph_card = {
.of_match_table = graph_of_tegra_match,
},
.probe = tegra_audio_graph_probe,
- .remove = audio_graph_remove,
+ .remove = asoc_simple_remove,
};
module_platform_driver(tegra_audio_graph_card);