mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	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>
This commit is contained in:
		
							parent
							
								
									091aa42053
								
							
						
					
					
						commit
						707e0759f2
					
				
					 1 changed files with 33 additions and 16 deletions
				
			
		| 
						 | 
					@ -233,32 +233,24 @@ static void hda_tegra_disable_clocks(struct hda_tegra *data)
 | 
				
			||||||
static int hda_tegra_suspend(struct device *dev)
 | 
					static int hda_tegra_suspend(struct device *dev)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct snd_card *card = dev_get_drvdata(dev);
 | 
						struct snd_card *card = dev_get_drvdata(dev);
 | 
				
			||||||
	struct azx *chip = card->private_data;
 | 
						int rc;
 | 
				
			||||||
	struct hda_tegra *hda = container_of(chip, struct hda_tegra, chip);
 | 
					 | 
				
			||||||
	struct hdac_bus *bus = azx_bus(chip);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						rc = pm_runtime_force_suspend(dev);
 | 
				
			||||||
 | 
						if (rc < 0)
 | 
				
			||||||
 | 
							return rc;
 | 
				
			||||||
	snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
 | 
						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;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int hda_tegra_resume(struct device *dev)
 | 
					static int hda_tegra_resume(struct device *dev)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct snd_card *card = dev_get_drvdata(dev);
 | 
						struct snd_card *card = dev_get_drvdata(dev);
 | 
				
			||||||
	struct azx *chip = card->private_data;
 | 
						int rc;
 | 
				
			||||||
	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);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						rc = pm_runtime_force_resume(dev);
 | 
				
			||||||
 | 
						if (rc < 0)
 | 
				
			||||||
 | 
							return rc;
 | 
				
			||||||
	snd_power_change_state(card, SNDRV_CTL_POWER_D0);
 | 
						snd_power_change_state(card, SNDRV_CTL_POWER_D0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
| 
						 | 
					@ -268,11 +260,36 @@ static int hda_tegra_resume(struct device *dev)
 | 
				
			||||||
#ifdef CONFIG_PM
 | 
					#ifdef CONFIG_PM
 | 
				
			||||||
static int hda_tegra_runtime_suspend(struct device *dev)
 | 
					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;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int hda_tegra_runtime_resume(struct device *dev)
 | 
					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;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
#endif /* CONFIG_PM */
 | 
					#endif /* CONFIG_PM */
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue