Skip to content

Commit

Permalink
ASoC: tegra30: i2s: Restore hardware state on runtime PM resume
Browse files Browse the repository at this point in the history
Tegra30 I2S driver syncs regmap cache only on resume from system suspend,
but hardware is reset across the runtime suspend because RPM of the parent
AHUB driver resets the I2S hardware, hence h/w state is lost after each
RPM resume. The problem isn't visible because hardware happens to be fully
reprogrammed after each RPM resume. Move hardware syncing to RPM resume in
order to restore h/w state properly.

Fixes: ed9ce1e ("ASoC: tegra: ahub: Reset hardware properly")
Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
Link: https://lore.kernel.org/r/20210314154459.15375-4-digetx@gmail.com
Signed-off-by: Mark Brown <broonie@kernel.org>
  • Loading branch information
Dmitry Osipenko authored and Mark Brown committed Mar 18, 2021
1 parent 9c648ef commit 0bbceca
Showing 1 changed file with 12 additions and 28 deletions.
40 changes: 12 additions & 28 deletions sound/soc/tegra/tegra30_i2s.c
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,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,
Expand Down Expand Up @@ -551,37 +561,11 @@ static int tegra30_i2s_platform_remove(struct platform_device *pdev)
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);

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 = {
Expand Down

0 comments on commit 0bbceca

Please sign in to comment.