summaryrefslogtreecommitdiff
path: root/sound/soc/tegra/tegra20_i2s.c
diff options
context:
space:
mode:
authorNikesh Oswal <noswal@nvidia.com>2011-12-13 15:10:28 +0530
committerVarun Wadekar <vwadekar@nvidia.com>2011-12-15 12:11:53 +0530
commitc7eca96f46f1162893f1031d406e22d2e20b061a (patch)
treee4b48cbea1c90cf2235f5b93f72823be03e51872 /sound/soc/tegra/tegra20_i2s.c
parente3794ce5d5d055f9e7939874297e0fe12e41e619 (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.c51
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,