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_i2s.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_i2s.c')
-rw-r--r-- | sound/soc/tegra/tegra20_i2s.c | 51 |
1 files changed, 51 insertions, 0 deletions
diff --git a/sound/soc/tegra/tegra20_i2s.c b/sound/soc/tegra/tegra20_i2s.c index 3f83887a7185..c8682302b4aa 100644 --- a/sound/soc/tegra/tegra20_i2s.c +++ b/sound/soc/tegra/tegra20_i2s.c @@ -49,6 +49,9 @@ static inline void tegra20_i2s_write(struct tegra20_i2s *i2s, u32 reg, u32 val) { +#ifdef CONFIG_PM + i2s->reg_cache[reg >> 2] = val; +#endif __raw_writel(val, i2s->regs + reg); } @@ -336,13 +339,59 @@ static int tegra20_i2s_trigger(struct snd_pcm_substream *substream, int cmd, static int tegra20_i2s_probe(struct snd_soc_dai *dai) { struct tegra20_i2s * i2s = snd_soc_dai_get_drvdata(dai); +#ifdef CONFIG_PM + int i; +#endif dai->capture_dma_data = &i2s->capture_dma_data; dai->playback_dma_data = &i2s->playback_dma_data; +#ifdef CONFIG_PM + /* populate the i2s reg cache with POR values*/ + clk_enable(i2s->clk_i2s); + + for (i = 0; i < ((TEGRA20_I2S_TDM_TX_RX_CTRL >> 2) + 1); i++) { + if ((i == TEGRA20_I2S_CACHE_RSVD_6) || + (i == TEGRA20_I2S_CACHE_RSVD_7)) + continue; + + i2s->reg_cache[i] = tegra20_i2s_read(i2s, i << 2); + } + + clk_disable(i2s->clk_i2s); +#endif + return 0; } +#ifdef CONFIG_PM +int tegra20_i2s_resume(struct snd_soc_dai *cpu_dai) +{ + struct tegra20_i2s *i2s = snd_soc_dai_get_drvdata(cpu_dai); + int i; + + clk_enable(i2s->clk_i2s); + + /*restore the i2s regs*/ + for (i = 0; i < ((TEGRA20_I2S_TDM_TX_RX_CTRL >> 2) + 1); i++) { + if ((i == TEGRA20_I2S_CACHE_RSVD_6) || + (i == TEGRA20_I2S_CACHE_RSVD_7)) + continue; + + tegra20_i2s_write(i2s, i << 2, i2s->reg_cache[i]); + } + + /*restore the das regs*/ + tegra20_das_resume(); + + clk_disable(i2s->clk_i2s); + + return 0; +} +#else +#define tegra20_i2s_resume NULL +#endif + static struct snd_soc_dai_ops tegra20_i2s_dai_ops = { .set_fmt = tegra20_i2s_set_fmt, .hw_params = tegra20_i2s_hw_params, @@ -353,6 +402,7 @@ struct snd_soc_dai_driver tegra20_i2s_dai[] = { { .name = DRV_NAME ".0", .probe = tegra20_i2s_probe, + .resume = tegra20_i2s_resume, .playback = { .channels_min = 1, .channels_max = 2, @@ -371,6 +421,7 @@ struct snd_soc_dai_driver tegra20_i2s_dai[] = { { .name = DRV_NAME ".1", .probe = tegra20_i2s_probe, + .resume = tegra20_i2s_resume, .playback = { .channels_min = 1, .channels_max = 2, |