summaryrefslogtreecommitdiffstats
path: root/sound/pci
diff options
context:
space:
mode:
authorSameer Pujar <spujar@nvidia.com>2019-01-22 13:03:20 +0530
committerTakashi Iwai <tiwai@suse.de>2019-01-22 09:21:56 +0100
commit707e0759f2f4aefcc5c3f08ce5fb9e98495fdc93 (patch)
tree03d5df1b09318a2638d8d970fb2e61379bfa7e6c /sound/pci
parent091aa420530c1f0c93745dc9e506bfa96f898702 (diff)
downloadlinux-707e0759f2f4aefcc5c3f08ce5fb9e98495fdc93.tar.bz2
ALSA: hda/tegra: implement runtime suspend/resume
This patch moves clock enable/disable from system resume/suspend to runtime resume/suspend respectively. Along with this hda controller chip init or stop is also moved. System resume/suspend can invoke runtime callbacks and do necessary setup. chip->running can be used to check for probe completion and device access during runtime_resume or runtime_suspend can be avoided if probe is not yet finished. This helps to avoid kernel panic during boot where runtime PM callbacks can happen from system PM. Signed-off-by: Sameer Pujar <spujar@nvidia.com> Reviewed-by: Ravindra Lokhande <rlokhande@nvidia.com> Reviewed-by: Mohan Kumar D <mkumard@nvidia.com> Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/pci')
-rw-r--r--sound/pci/hda/hda_tegra.c49
1 files changed, 33 insertions, 16 deletions
diff --git a/sound/pci/hda/hda_tegra.c b/sound/pci/hda/hda_tegra.c
index f068b1e7719b..a7fd4c67ab8e 100644
--- a/sound/pci/hda/hda_tegra.c
+++ b/sound/pci/hda/hda_tegra.c
@@ -233,32 +233,24 @@ static void hda_tegra_disable_clocks(struct hda_tegra *data)
static int hda_tegra_suspend(struct device *dev)
{
struct snd_card *card = dev_get_drvdata(dev);
- struct azx *chip = card->private_data;
- struct hda_tegra *hda = container_of(chip, struct hda_tegra, chip);
- struct hdac_bus *bus = azx_bus(chip);
+ int rc;
+ rc = pm_runtime_force_suspend(dev);
+ if (rc < 0)
+ return rc;
snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
- azx_stop_chip(chip);
- synchronize_irq(bus->irq);
- azx_enter_link_reset(chip);
- hda_tegra_disable_clocks(hda);
-
return 0;
}
static int hda_tegra_resume(struct device *dev)
{
struct snd_card *card = dev_get_drvdata(dev);
- struct azx *chip = card->private_data;
- struct hda_tegra *hda = container_of(chip, struct hda_tegra, chip);
-
- hda_tegra_enable_clocks(hda);
-
- hda_tegra_init(hda);
-
- azx_init_chip(chip, 1);
+ int rc;
+ rc = pm_runtime_force_resume(dev);
+ if (rc < 0)
+ return rc;
snd_power_change_state(card, SNDRV_CTL_POWER_D0);
return 0;
@@ -268,11 +260,36 @@ static int hda_tegra_resume(struct device *dev)
#ifdef CONFIG_PM
static int hda_tegra_runtime_suspend(struct device *dev)
{
+ struct snd_card *card = dev_get_drvdata(dev);
+ struct azx *chip = card->private_data;
+ struct hda_tegra *hda = container_of(chip, struct hda_tegra, chip);
+ struct hdac_bus *bus = azx_bus(chip);
+
+ if (chip && chip->running) {
+ azx_stop_chip(chip);
+ synchronize_irq(bus->irq);
+ azx_enter_link_reset(chip);
+ }
+ hda_tegra_disable_clocks(hda);
+
return 0;
}
static int hda_tegra_runtime_resume(struct device *dev)
{
+ struct snd_card *card = dev_get_drvdata(dev);
+ struct azx *chip = card->private_data;
+ struct hda_tegra *hda = container_of(chip, struct hda_tegra, chip);
+ int rc;
+
+ rc = hda_tegra_enable_clocks(hda);
+ if (rc != 0)
+ return rc;
+ if (chip && chip->running) {
+ hda_tegra_init(hda);
+ azx_init_chip(chip, 1);
+ }
+
return 0;
}
#endif /* CONFIG_PM */