diff options
Diffstat (limited to 'sound/soc/tegra')
-rw-r--r-- | sound/soc/tegra/tegra20_ac97.c | 21 | ||||
-rw-r--r-- | sound/soc/tegra/tegra20_ac97.h | 1 | ||||
-rw-r--r-- | sound/soc/tegra/tegra20_das.c | 8 | ||||
-rw-r--r-- | sound/soc/tegra/tegra20_das.h | 6 | ||||
-rw-r--r-- | sound/soc/tegra/tegra20_i2s.c | 64 | ||||
-rw-r--r-- | sound/soc/tegra/tegra20_i2s.h | 1 | ||||
-rw-r--r-- | sound/soc/tegra/tegra20_spdif.c | 20 | ||||
-rw-r--r-- | sound/soc/tegra/tegra30_ahub.c | 172 | ||||
-rw-r--r-- | sound/soc/tegra/tegra30_ahub.h | 5 | ||||
-rw-r--r-- | sound/soc/tegra/tegra30_i2s.c | 69 | ||||
-rw-r--r-- | sound/soc/tegra/tegra_audio_graph_card.c | 5 |
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); |