From 1f080ab1eb8e44ae5f352170b0a14dfc7eba2b6d Mon Sep 17 00:00:00 2001 From: Sumit Bhattacharya Date: Mon, 18 Aug 2014 13:38:49 +0530 Subject: [PATCH] ASoC: tegra-alt: T210 power management support Set idle_bias_off for all t210 xbar modules to ensure module runtime suspend/resume works when module is idle. Ensure regcache is synced back to hardware during runtime resume so that register content does not get lost if it is written during runtime suspend state. Add suspend APIs for all module to mark regcache dirty while device goes into suspend to ensure register values does not get lost across system suspend/resume. Change-Id: I2828beeed859df4f8084dd70bbcde5ed62f2525c Signed-off-by: Sumit Bhattacharya Reviewed-on: http://git-master/r/555028 Reviewed-by: Automatic_Commit_Validation_User Reviewed-by: Arun Shamanna Lakshmi GVS: Gerrit_Virtual_Submit --- sound/soc/tegra-alt/tegra210_admaif_alt.c | 13 +++++++++++++ sound/soc/tegra-alt/tegra210_adx_alt.c | 13 +++++++++++++ sound/soc/tegra-alt/tegra210_afc_alt.c | 13 +++++++++++++ sound/soc/tegra-alt/tegra210_amx_alt.c | 13 +++++++++++++ sound/soc/tegra-alt/tegra210_dmic_alt.c | 14 ++++++++++++++ sound/soc/tegra-alt/tegra210_i2s_alt.c | 14 ++++++++++++++ sound/soc/tegra-alt/tegra210_iqc_alt.c | 13 +++++++++++++ sound/soc/tegra-alt/tegra210_mixer_alt.c | 13 +++++++++++++ sound/soc/tegra-alt/tegra210_mvc_alt.c | 13 +++++++++++++ sound/soc/tegra-alt/tegra210_ope_alt.c | 17 +++++++++++++++++ sound/soc/tegra-alt/tegra210_sfc_alt.c | 13 +++++++++++++ sound/soc/tegra-alt/tegra210_spdif_alt.c | 13 +++++++++++++ sound/soc/tegra-alt/tegra210_xbar_alt.c | 18 +++++++++++++++++- 13 files changed, 179 insertions(+), 1 deletion(-) diff --git a/sound/soc/tegra-alt/tegra210_admaif_alt.c b/sound/soc/tegra-alt/tegra210_admaif_alt.c index 56508630..bf2da81f 100644 --- a/sound/soc/tegra-alt/tegra210_admaif_alt.c +++ b/sound/soc/tegra-alt/tegra210_admaif_alt.c @@ -204,10 +204,21 @@ static int tegra210_admaif_runtime_resume(struct device *dev) } regcache_cache_only(admaif->regmap, false); + regcache_sync(admaif->regmap); return 0; } +#ifdef CONFIG_PM_SLEEP +static int tegra210_admaif_suspend(struct device *dev) +{ + struct tegra210_admaif *admaif = dev_get_drvdata(dev); + + regcache_mark_dirty(admaif->regmap); + return 0; +} +#endif + static int tegra210_admaif_set_pack_mode(struct regmap *map, unsigned int reg, int valid_bit) { @@ -593,6 +604,7 @@ static struct snd_soc_codec_driver tegra210_admaif_codec = { .num_dapm_widgets = ARRAY_SIZE(tegra210_admaif_widgets), .dapm_routes = tegra210_admaif_routes, .num_dapm_routes = ARRAY_SIZE(tegra210_admaif_routes), + .idle_bias_off = 1, }; static const struct snd_soc_component_driver tegra210_admaif_dai_driver = { @@ -797,6 +809,7 @@ static int tegra210_admaif_remove(struct platform_device *pdev) static const struct dev_pm_ops tegra210_admaif_pm_ops = { SET_RUNTIME_PM_OPS(tegra210_admaif_runtime_suspend, tegra210_admaif_runtime_resume, NULL) + SET_SYSTEM_SLEEP_PM_OPS(tegra210_admaif_suspend, NULL) }; static struct platform_driver tegra210_admaif_driver = { diff --git a/sound/soc/tegra-alt/tegra210_adx_alt.c b/sound/soc/tegra-alt/tegra210_adx_alt.c index c0746342..cf8034d9 100644 --- a/sound/soc/tegra-alt/tegra210_adx_alt.c +++ b/sound/soc/tegra-alt/tegra210_adx_alt.c @@ -252,10 +252,21 @@ static int tegra210_adx_runtime_resume(struct device *dev) } regcache_cache_only(adx->regmap, false); + regcache_sync(adx->regmap); return 0; } +#ifdef CONFIG_PM_SLEEP +static int tegra210_adx_suspend(struct device *dev) +{ + struct tegra210_adx *adx = dev_get_drvdata(dev); + + regcache_mark_dirty(adx->regmap); + return 0; +} +#endif + static int tegra210_adx_set_audio_cif(struct tegra210_adx *adx, struct snd_pcm_hw_params *params, unsigned int reg) @@ -493,6 +504,7 @@ static struct snd_soc_codec_driver tegra210_adx_codec = { .num_dapm_widgets = ARRAY_SIZE(tegra210_adx_widgets), .dapm_routes = tegra210_adx_routes, .num_dapm_routes = ARRAY_SIZE(tegra210_adx_routes), + .idle_bias_off = 1, }; static bool tegra210_adx_wr_reg(struct device *dev, @@ -711,6 +723,7 @@ static int tegra210_adx_platform_remove(struct platform_device *pdev) static const struct dev_pm_ops tegra210_adx_pm_ops = { SET_RUNTIME_PM_OPS(tegra210_adx_runtime_suspend, tegra210_adx_runtime_resume, NULL) + SET_SYSTEM_SLEEP_PM_OPS(tegra210_adx_suspend, NULL) }; static struct platform_driver tegra210_adx_driver = { diff --git a/sound/soc/tegra-alt/tegra210_afc_alt.c b/sound/soc/tegra-alt/tegra210_afc_alt.c index a475bab4..0e69d90d 100644 --- a/sound/soc/tegra-alt/tegra210_afc_alt.c +++ b/sound/soc/tegra-alt/tegra210_afc_alt.c @@ -60,10 +60,21 @@ static int tegra210_afc_runtime_resume(struct device *dev) } regcache_cache_only(afc->regmap, false); + regcache_sync(afc->regmap); return 0; } +#ifdef CONFIG_PM_SLEEP +static int tegra210_afc_suspend(struct device *dev) +{ + struct tegra210_afc *afc = dev_get_drvdata(dev); + + regcache_mark_dirty(afc->regmap); + return 0; +} +#endif + /* returns the destination I2S id connected along the AFC path */ static unsigned int tegra210_afc_get_i2s_id(unsigned int afc_id) { @@ -265,6 +276,7 @@ static struct snd_soc_codec_driver tegra210_afc_codec = { .num_dapm_widgets = ARRAY_SIZE(tegra210_afc_widgets), .dapm_routes = tegra210_afc_routes, .num_dapm_routes = ARRAY_SIZE(tegra210_afc_routes), + .idle_bias_off = 1, }; static bool tegra210_afc_wr_rd_reg(struct device *dev, unsigned int reg) @@ -451,6 +463,7 @@ static int tegra210_afc_platform_remove(struct platform_device *pdev) static const struct dev_pm_ops tegra210_afc_pm_ops = { SET_RUNTIME_PM_OPS(tegra210_afc_runtime_suspend, tegra210_afc_runtime_resume, NULL) + SET_SYSTEM_SLEEP_PM_OPS(tegra210_afc_suspend, NULL) }; static struct platform_driver tegra210_afc_driver = { diff --git a/sound/soc/tegra-alt/tegra210_amx_alt.c b/sound/soc/tegra-alt/tegra210_amx_alt.c index 9cec5f35..10ab6007 100644 --- a/sound/soc/tegra-alt/tegra210_amx_alt.c +++ b/sound/soc/tegra-alt/tegra210_amx_alt.c @@ -278,10 +278,21 @@ static int tegra210_amx_runtime_resume(struct device *dev) } regcache_cache_only(amx->regmap, false); + regcache_sync(amx->regmap); return 0; } +#ifdef CONFIG_PM_SLEEP +static int tegra210_amx_suspend(struct device *dev) +{ + struct tegra210_amx *amx = dev_get_drvdata(dev); + + regcache_mark_dirty(amx->regmap); + return 0; +} +#endif + static int tegra210_amx_set_audio_cif(struct tegra210_amx *amx, struct snd_pcm_hw_params *params, unsigned int reg) @@ -525,6 +536,7 @@ static struct snd_soc_codec_driver tegra210_amx_codec = { .num_dapm_widgets = ARRAY_SIZE(tegra210_amx_widgets), .dapm_routes = tegra210_amx_routes, .num_dapm_routes = ARRAY_SIZE(tegra210_amx_routes), + .idle_bias_off = 1, }; static bool tegra210_amx_wr_reg(struct device *dev, @@ -744,6 +756,7 @@ static int tegra210_amx_platform_remove(struct platform_device *pdev) static const struct dev_pm_ops tegra210_amx_pm_ops = { SET_RUNTIME_PM_OPS(tegra210_amx_runtime_suspend, tegra210_amx_runtime_resume, NULL) + SET_SYSTEM_SLEEP_PM_OPS(tegra210_amx_suspend, NULL) }; static struct platform_driver tegra210_amx_driver = { diff --git a/sound/soc/tegra-alt/tegra210_dmic_alt.c b/sound/soc/tegra-alt/tegra210_dmic_alt.c index b91ef575..29a14f81 100644 --- a/sound/soc/tegra-alt/tegra210_dmic_alt.c +++ b/sound/soc/tegra-alt/tegra210_dmic_alt.c @@ -70,9 +70,21 @@ static int tegra210_dmic_runtime_resume(struct device *dev) #endif regcache_cache_only(dmic->regmap, false); + regcache_sync(dmic->regmap); + return 0; } +#ifdef CONFIG_PM_SLEEP +static int tegra210_dmic_suspend(struct device *dev) +{ + struct tegra210_dmic *dmic = dev_get_drvdata(dev); + + regcache_mark_dirty(dmic->regmap); + return 0; +} +#endif + static int tegra210_dmic_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) @@ -201,6 +213,7 @@ static struct snd_soc_codec_driver tegra210_dmic_codec = { .num_dapm_widgets = ARRAY_SIZE(tegra210_dmic_widgets), .dapm_routes = tegra210_dmic_routes, .num_dapm_routes = ARRAY_SIZE(tegra210_dmic_routes), + .idle_bias_off = 1, }; /* Regmap callback functions */ @@ -415,6 +428,7 @@ static int tegra210_dmic_platform_remove(struct platform_device *pdev) static const struct dev_pm_ops tegra210_dmic_pm_ops = { SET_RUNTIME_PM_OPS(tegra210_dmic_runtime_suspend, tegra210_dmic_runtime_resume, NULL) + SET_SYSTEM_SLEEP_PM_OPS(tegra210_dmic_suspend, NULL) }; static struct platform_driver tegra210_dmic_driver = { diff --git a/sound/soc/tegra-alt/tegra210_i2s_alt.c b/sound/soc/tegra-alt/tegra210_i2s_alt.c index f1f67a43..521543e5 100644 --- a/sound/soc/tegra-alt/tegra210_i2s_alt.c +++ b/sound/soc/tegra-alt/tegra210_i2s_alt.c @@ -259,11 +259,23 @@ static int tegra210_i2s_runtime_resume(struct device *dev) dev_err(dev, "clk_enable failed: %d\n", ret); return ret; } + regcache_cache_only(i2s->regmap, false); + regcache_sync(i2s->regmap); return 0; } +#ifdef CONFIG_PM_SLEEP +static int tegra210_i2s_suspend(struct device *dev) +{ + struct tegra210_i2s *i2s = dev_get_drvdata(dev); + + regcache_mark_dirty(i2s->regmap); + return 0; +} +#endif + static int tegra210_i2s_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) { @@ -630,6 +642,7 @@ static struct snd_soc_codec_driver tegra210_i2s_codec = { .num_dapm_routes = ARRAY_SIZE(tegra210_i2s_routes), .controls = tegra210_i2s_controls, .num_controls = ARRAY_SIZE(tegra210_i2s_controls), + .idle_bias_off = 1, }; static bool tegra210_i2s_wr_reg(struct device *dev, unsigned int reg) @@ -962,6 +975,7 @@ static int tegra210_i2s_platform_remove(struct platform_device *pdev) static const struct dev_pm_ops tegra210_i2s_pm_ops = { SET_RUNTIME_PM_OPS(tegra210_i2s_runtime_suspend, tegra210_i2s_runtime_resume, NULL) + SET_SYSTEM_SLEEP_PM_OPS(tegra210_i2s_suspend, NULL) }; static struct platform_driver tegra210_i2s_driver = { diff --git a/sound/soc/tegra-alt/tegra210_iqc_alt.c b/sound/soc/tegra-alt/tegra210_iqc_alt.c index 874befad..c0bbb894 100644 --- a/sound/soc/tegra-alt/tegra210_iqc_alt.c +++ b/sound/soc/tegra-alt/tegra210_iqc_alt.c @@ -71,10 +71,21 @@ static int tegra210_iqc_runtime_resume(struct device *dev) #endif regcache_cache_only(iqc->regmap, false); + regcache_sync(iqc->regmap); return 0; } +#ifdef CONFIG_PM_SLEEP +static int tegra210_iqc_suspend(struct device *dev) +{ + struct tegra210_iqc *iqc = dev_get_drvdata(dev); + + regcache_mark_dirty(iqc->regmap); + return 0; +} +#endif + static int tegra210_iqc_set_audio_cif(struct tegra210_iqc *iqc, struct snd_pcm_hw_params *params, unsigned int reg) @@ -230,6 +241,7 @@ static struct snd_soc_codec_driver tegra210_iqc_codec = { .num_dapm_routes = ARRAY_SIZE(tegra210_iqc_routes), .controls = tegra210_iqc_controls, .num_controls = ARRAY_SIZE(tegra210_iqc_controls), + .idle_bias_off = 1, }; static bool tegra210_iqc_wr_reg(struct device *dev, unsigned int reg) @@ -443,6 +455,7 @@ static int tegra210_iqc_platform_remove(struct platform_device *pdev) static const struct dev_pm_ops tegra210_iqc_pm_ops = { SET_RUNTIME_PM_OPS(tegra210_iqc_runtime_suspend, tegra210_iqc_runtime_resume, NULL) + SET_SYSTEM_SLEEP_PM_OPS(tegra210_iqc_suspend, NULL) }; static struct platform_driver tegra210_iqc_driver = { diff --git a/sound/soc/tegra-alt/tegra210_mixer_alt.c b/sound/soc/tegra-alt/tegra210_mixer_alt.c index 76bd5ed3..fffbf639 100644 --- a/sound/soc/tegra-alt/tegra210_mixer_alt.c +++ b/sound/soc/tegra-alt/tegra210_mixer_alt.c @@ -63,10 +63,21 @@ static int tegra210_mixer_runtime_resume(struct device *dev) } regcache_cache_only(mixer->regmap, false); + regcache_sync(mixer->regmap); return 0; } +#ifdef CONFIG_PM_SLEEP +static int tegra210_mixer_suspend(struct device *dev) +{ + struct tegra210_mixer *mixer = dev_get_drvdata(dev); + + regcache_mark_dirty(mixer->regmap); + return 0; +} +#endif + static int tegra210_mixer_write_ram(struct tegra210_mixer *mixer, unsigned int addr, unsigned int val) @@ -389,6 +400,7 @@ static struct snd_soc_codec_driver tegra210_mixer_codec = { .num_dapm_routes = ARRAY_SIZE(tegra210_mixer_routes), .controls = tegra210_mixer_gain_ctls, .num_controls = ARRAY_SIZE(tegra210_mixer_gain_ctls), + .idle_bias_off = 1, }; static bool tegra210_mixer_wr_reg(struct device *dev, @@ -658,6 +670,7 @@ static int tegra210_mixer_platform_remove(struct platform_device *pdev) static const struct dev_pm_ops tegra210_mixer_pm_ops = { SET_RUNTIME_PM_OPS(tegra210_mixer_runtime_suspend, tegra210_mixer_runtime_resume, NULL) + SET_SYSTEM_SLEEP_PM_OPS(tegra210_mixer_suspend, NULL) }; static struct platform_driver tegra210_mixer_driver = { diff --git a/sound/soc/tegra-alt/tegra210_mvc_alt.c b/sound/soc/tegra-alt/tegra210_mvc_alt.c index 3fb0465a..c4778317 100644 --- a/sound/soc/tegra-alt/tegra210_mvc_alt.c +++ b/sound/soc/tegra-alt/tegra210_mvc_alt.c @@ -59,10 +59,21 @@ static int tegra210_mvc_runtime_resume(struct device *dev) } regcache_cache_only(mvc->regmap, false); + regcache_sync(mvc->regmap); return 0; } +#ifdef CONFIG_PM_SLEEP +static int tegra210_mvc_suspend(struct device *dev) +{ + struct tegra210_mvc *mvc = dev_get_drvdata(dev); + + regcache_mark_dirty(mvc->regmap); + return 0; +} +#endif + static int tegra210_mvc_write_ram(struct tegra210_mvc *mvc, unsigned int addr, unsigned int val) @@ -289,6 +300,7 @@ static struct snd_soc_codec_driver tegra210_mvc_codec = { .num_dapm_routes = ARRAY_SIZE(tegra210_mvc_routes), .controls = tegra210_mvc_vol_ctrl, .num_controls = ARRAY_SIZE(tegra210_mvc_vol_ctrl), + .idle_bias_off = 1, }; static bool tegra210_mvc_wr_rd_reg(struct device *dev, unsigned int reg) @@ -501,6 +513,7 @@ static int tegra210_mvc_platform_remove(struct platform_device *pdev) static const struct dev_pm_ops tegra210_mvc_pm_ops = { SET_RUNTIME_PM_OPS(tegra210_mvc_runtime_suspend, tegra210_mvc_runtime_resume, NULL) + SET_SYSTEM_SLEEP_PM_OPS(tegra210_mvc_suspend, NULL) }; static struct platform_driver tegra210_mvc_driver = { diff --git a/sound/soc/tegra-alt/tegra210_ope_alt.c b/sound/soc/tegra-alt/tegra210_ope_alt.c index cc9611ee..2f2fd765 100644 --- a/sound/soc/tegra-alt/tegra210_ope_alt.c +++ b/sound/soc/tegra-alt/tegra210_ope_alt.c @@ -64,10 +64,25 @@ static int tegra210_ope_runtime_resume(struct device *dev) regcache_cache_only(ope->regmap, false); regcache_cache_only(ope->peq_regmap, false); regcache_cache_only(ope->mbdrc_regmap, false); + regcache_sync(ope->regmap); + regcache_sync(ope->peq_regmap); + regcache_sync(ope->mbdrc_regmap); return 0; } +#ifdef CONFIG_PM_SLEEP +static int tegra210_ope_suspend(struct device *dev) +{ + struct tegra210_ope *ope = dev_get_drvdata(dev); + + regcache_mark_dirty(ope->regmap); + regcache_mark_dirty(ope->peq_regmap); + regcache_mark_dirty(ope->mbdrc_regmap); + return 0; +} +#endif + static int tegra210_ope_set_audio_cif(struct tegra210_ope *ope, struct snd_pcm_hw_params *params, unsigned int reg) @@ -204,6 +219,7 @@ static struct snd_soc_codec_driver tegra210_ope_codec = { .num_dapm_routes = ARRAY_SIZE(tegra210_ope_routes), .controls = tegra210_ope_controls, .num_controls = ARRAY_SIZE(tegra210_ope_controls), + .idle_bias_off = 1, }; static bool tegra210_ope_wr_reg(struct device *dev, unsigned int reg) @@ -433,6 +449,7 @@ static int tegra210_ope_platform_remove(struct platform_device *pdev) static const struct dev_pm_ops tegra210_ope_pm_ops = { SET_RUNTIME_PM_OPS(tegra210_ope_runtime_suspend, tegra210_ope_runtime_resume, NULL) + SET_SYSTEM_SLEEP_PM_OPS(tegra210_ope_suspend, NULL) }; static struct platform_driver tegra210_ope_driver = { diff --git a/sound/soc/tegra-alt/tegra210_sfc_alt.c b/sound/soc/tegra-alt/tegra210_sfc_alt.c index 50095f3f..51d220c5 100644 --- a/sound/soc/tegra-alt/tegra210_sfc_alt.c +++ b/sound/soc/tegra-alt/tegra210_sfc_alt.c @@ -59,10 +59,21 @@ static int tegra210_sfc_runtime_resume(struct device *dev) } regcache_cache_only(sfc->regmap, false); + regcache_sync(sfc->regmap); return 0; } +#ifdef CONFIG_PM_SLEEP +static int tegra210_sfc_suspend(struct device *dev) +{ + struct tegra210_sfc *sfc = dev_get_drvdata(dev); + + regcache_mark_dirty(sfc->regmap); + return 0; +} +#endif + static int tegra210_sfc_set_dai_sysclk(struct snd_soc_dai *dai, int clk_id, unsigned int freq, int dir) { @@ -323,6 +334,7 @@ static struct snd_soc_codec_driver tegra210_sfc_codec = { .num_dapm_routes = ARRAY_SIZE(tegra210_sfc_routes), .controls = tegra210_sfc_controls, .num_controls = ARRAY_SIZE(tegra210_sfc_controls), + .idle_bias_off = 1, }; static bool tegra210_sfc_wr_reg(struct device *dev, unsigned int reg) @@ -548,6 +560,7 @@ static int tegra210_sfc_platform_remove(struct platform_device *pdev) static const struct dev_pm_ops tegra210_sfc_pm_ops = { SET_RUNTIME_PM_OPS(tegra210_sfc_runtime_suspend, tegra210_sfc_runtime_resume, NULL) + SET_SYSTEM_SLEEP_PM_OPS(tegra210_sfc_suspend, NULL) }; static struct platform_driver tegra210_sfc_driver = { diff --git a/sound/soc/tegra-alt/tegra210_spdif_alt.c b/sound/soc/tegra-alt/tegra210_spdif_alt.c index fcb1e1d8..17ffaab2 100644 --- a/sound/soc/tegra-alt/tegra210_spdif_alt.c +++ b/sound/soc/tegra-alt/tegra210_spdif_alt.c @@ -73,10 +73,21 @@ static int tegra210_spdif_runtime_resume(struct device *dev) } regcache_cache_only(spdif->regmap, false); + regcache_sync(spdif->regmap); return ret; } +#ifdef CONFIG_PM_SLEEP +static int tegra210_spdif_suspend(struct device *dev) +{ + struct tegra210_spdif *spdif = dev_get_drvdata(dev); + + regcache_mark_dirty(spdif->regmap); + return 0; +} +#endif + static int tegra210_spdif_set_dai_sysclk(struct snd_soc_dai *dai, int clk_id, unsigned int freq, int dir) { @@ -271,6 +282,7 @@ static struct snd_soc_codec_driver tegra210_spdif_codec = { .num_dapm_widgets = ARRAY_SIZE(tegra210_spdif_widgets), .dapm_routes = tegra210_spdif_routes, .num_dapm_routes = ARRAY_SIZE(tegra210_spdif_routes), + .idle_bias_off = 1, }; static bool tegra210_spdif_wr_rd_reg(struct device *dev, unsigned int reg) @@ -465,6 +477,7 @@ static int tegra210_spdif_platform_remove(struct platform_device *pdev) static const struct dev_pm_ops tegra210_spdif_pm_ops = { SET_RUNTIME_PM_OPS(tegra210_spdif_runtime_suspend, tegra210_spdif_runtime_resume, NULL) + SET_SYSTEM_SLEEP_PM_OPS(tegra210_spdif_suspend, NULL) }; static struct platform_driver tegra210_spdif_driver = { diff --git a/sound/soc/tegra-alt/tegra210_xbar_alt.c b/sound/soc/tegra-alt/tegra210_xbar_alt.c index 7b735477..10d9dbc4 100644 --- a/sound/soc/tegra-alt/tegra210_xbar_alt.c +++ b/sound/soc/tegra-alt/tegra210_xbar_alt.c @@ -34,18 +34,23 @@ struct tegra210_xbar *xbar; +static bool tegra210_xbar_volatile_reg(struct device *dev, unsigned int reg) +{ + return false; +} + static const struct regmap_config tegra210_xbar_regmap_config = { .reg_bits = 32, .val_bits = 32, .reg_stride = 4, .max_register = TEGRA210_XBAR_PART2_RX + (TEGRA210_XBAR_RX_STRIDE * (TEGRA210_XBAR_AUDIO_RX_COUNT - 1)), + .volatile_reg = tegra210_xbar_volatile_reg, .cache_type = REGCACHE_FLAT, }; static int tegra210_xbar_runtime_suspend(struct device *dev) { - regcache_cache_only(xbar->regmap, true); clk_disable(xbar->clk); @@ -71,10 +76,19 @@ static int tegra210_xbar_runtime_resume(struct device *dev) } regcache_cache_only(xbar->regmap, false); + regcache_sync(xbar->regmap); return 0; } +#ifdef CONFIG_PM_SLEEP +static int tegra210_xbar_suspend(struct device *dev) +{ + regcache_mark_dirty(xbar->regmap); + return 0; +} +#endif + static int tegra210_xbar_codec_probe(struct snd_soc_codec *codec) { int ret; @@ -715,6 +729,7 @@ static struct snd_soc_codec_driver tegra210_xbar_codec = { .dapm_routes = tegra210_xbar_routes, .num_dapm_widgets = ARRAY_SIZE(tegra210_xbar_widgets), .num_dapm_routes = ARRAY_SIZE(tegra210_xbar_routes), + .idle_bias_off = 1, }; static const struct tegra210_xbar_soc_data soc_data_tegra210 = { @@ -942,6 +957,7 @@ static int tegra210_xbar_remove(struct platform_device *pdev) static const struct dev_pm_ops tegra210_xbar_pm_ops = { SET_RUNTIME_PM_OPS(tegra210_xbar_runtime_suspend, tegra210_xbar_runtime_resume, NULL) + SET_SYSTEM_SLEEP_PM_OPS(tegra210_xbar_suspend, NULL) }; static struct platform_driver tegra210_xbar_driver = {