Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 707e0759 authored by Sameer Pujar's avatar Sameer Pujar Committed by Takashi Iwai
Browse files

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: default avatarSameer Pujar <spujar@nvidia.com>
Reviewed-by: default avatarRavindra Lokhande <rlokhande@nvidia.com>
Reviewed-by: default avatarMohan Kumar D <mkumard@nvidia.com>
Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
parent 091aa420
Loading
Loading
Loading
Loading
+33 −16
Original line number Diff line number Diff line
@@ -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 */