diff options
author | Nikesh Oswal <noswal@nvidia.com> | 2011-12-13 15:10:28 +0530 |
---|---|---|
committer | Varun Wadekar <vwadekar@nvidia.com> | 2011-12-15 12:11:53 +0530 |
commit | c7eca96f46f1162893f1031d406e22d2e20b061a (patch) | |
tree | e4b48cbea1c90cf2235f5b93f72823be03e51872 /sound/soc/tegra/tegra20_spdif.c | |
parent | e3794ce5d5d055f9e7939874297e0fe12e41e619 (diff) |
asoc: tegra: restore i2s/das/spdif registers after suspend for t20
when system resumes from suspend state the i2s/das/spdif registers
have power on reset values, this change restores the registers
with their prior values from cache
Bug: 904530
Change-Id: I35c14d95d2d6bf5bc116a1a80e21f4904c8969e5
Signed-off-by: Nikesh Oswal <noswal@nvidia.com>
Reviewed-on: http://git-master/r/69715
Reviewed-by: Automatic_Commit_Validation_User
Reviewed-by: Sumit Bhattacharya <sumitb@nvidia.com>
Reviewed-by: Scott Peterson <speterson@nvidia.com>
Diffstat (limited to 'sound/soc/tegra/tegra20_spdif.c')
-rw-r--r-- | sound/soc/tegra/tegra20_spdif.c | 52 |
1 files changed, 52 insertions, 0 deletions
diff --git a/sound/soc/tegra/tegra20_spdif.c b/sound/soc/tegra/tegra20_spdif.c index e5ef59841566..3e747b5e1931 100644 --- a/sound/soc/tegra/tegra20_spdif.c +++ b/sound/soc/tegra/tegra20_spdif.c @@ -42,6 +42,13 @@ static inline void tegra20_spdif_write(struct tegra20_spdif *spdif, u32 reg, u32 val) { +#ifdef CONFIG_PM + if (reg < TEGRA20_SPDIF_CH_STA_TX_A) + spdif->reg_ctrl_cache[reg >> 2] = val; + else + spdif->reg_tx_cache[((reg - TEGRA20_SPDIF_CH_STA_TX_A) >> 2)] + = val; +#endif __raw_writel(val, spdif->regs + reg); } @@ -250,13 +257,57 @@ static int tegra20_spdif_trigger(struct snd_pcm_substream *substream, int cmd, static int tegra20_spdif_probe(struct snd_soc_dai *dai) { struct tegra20_spdif *spdif = snd_soc_dai_get_drvdata(dai); +#ifdef CONFIG_PM + int i, reg; +#endif dai->capture_dma_data = NULL; dai->playback_dma_data = &spdif->playback_dma_data; +#ifdef CONFIG_PM + clk_enable(spdif->clk_spdif_out); + + /* populate the spdif reg cache with POR values*/ + for (i = 0; i < TEGRA20_SPDIF_CTRL_CACHE_SIZE; i++) + spdif->reg_ctrl_cache[i] = tegra20_spdif_read(spdif, i << 2); + + for (i = 0; i < TEGRA20_SPDIF_TX_CACHE_SIZE; i++) { + reg = (TEGRA20_SPDIF_CH_STA_TX_A) + (i << 2); + spdif->reg_tx_cache[i] = tegra20_spdif_read(spdif, reg); + } + + clk_disable(spdif->clk_spdif_out); + +#endif + return 0; } +#ifdef CONFIG_PM +int tegra20_spdif_resume(struct snd_soc_dai *cpu_dai) +{ + struct tegra20_spdif *spdif = snd_soc_dai_get_drvdata(cpu_dai); + int i, reg; + + clk_enable(spdif->clk_spdif_out); + + /*restore the spdif regs*/ + for (i = 0; i < TEGRA20_SPDIF_CTRL_CACHE_SIZE; i++) + tegra20_spdif_write(spdif, i << 2, spdif->reg_ctrl_cache[i]); + + for (i = 0; i < TEGRA20_SPDIF_TX_CACHE_SIZE; i++) { + reg = (TEGRA20_SPDIF_CH_STA_TX_A) + (i << 2); + tegra20_spdif_write(spdif, reg, spdif->reg_tx_cache[i]); + } + + clk_disable(spdif->clk_spdif_out); + + return 0; +} +#else +#define tegra20_spdif_resume NULL +#endif + static struct snd_soc_dai_ops tegra20_spdif_dai_ops = { .hw_params = tegra20_spdif_hw_params, .trigger = tegra20_spdif_trigger, @@ -265,6 +316,7 @@ static struct snd_soc_dai_ops tegra20_spdif_dai_ops = { struct snd_soc_dai_driver tegra20_spdif_dai = { .name = DRV_NAME, .probe = tegra20_spdif_probe, + .resume = tegra20_spdif_resume, .playback = { .channels_min = 2, .channels_max = 2, |