From 707e0759f2f4aefcc5c3f08ce5fb9e98495fdc93 Mon Sep 17 00:00:00 2001 From: Sameer Pujar Date: Tue, 22 Jan 2019 13:03:20 +0530 Subject: 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 Reviewed-by: Ravindra Lokhande Reviewed-by: Mohan Kumar D Signed-off-by: Takashi Iwai --- sound/pci/hda/hda_tegra.c | 49 +++++++++++++++++++++++++++++++---------------- 1 file changed, 33 insertions(+), 16 deletions(-) (limited to 'sound/pci/hda/hda_tegra.c') 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 */ -- cgit v1.2.3