diff options
Diffstat (limited to 'sound/arm/tegra/hda_tegra.c')
-rw-r--r-- | sound/arm/tegra/hda_tegra.c | 73 |
1 files changed, 43 insertions, 30 deletions
diff --git a/sound/arm/tegra/hda_tegra.c b/sound/arm/tegra/hda_tegra.c index af1c26c25fca..63d207fd2980 100644 --- a/sound/arm/tegra/hda_tegra.c +++ b/sound/arm/tegra/hda_tegra.c @@ -53,6 +53,7 @@ static int enable_msi; /* Module clock info */ static struct clk *clk_hda, *clk_hda2codec , *clk_hda2hdmicodec; +static bool is_hda_clk_on = false; #ifdef CONFIG_SND_HDA_PATCH_LOADER static char *patch[SNDRV_CARDS]; @@ -448,6 +449,23 @@ azx_attach_pcm_stream(struct hda_bus *bus, struct hda_codec *codec, return 0; } +void nv_tegra_enable_hda_clks(bool on) +{ + if (on && !is_hda_clk_on) { + clk_enable(clk_hda); + clk_enable(clk_hda2codec); + clk_enable(clk_hda2hdmicodec); + msleep(1); + } + else if (!on && is_hda_clk_on) { + msleep(1); + clk_disable(clk_hda2hdmicodec); + clk_disable(clk_hda2codec); + clk_disable(clk_hda); + } + is_hda_clk_on = on; +} + #ifdef CONFIG_SND_HDA_POWER_SAVE /* power-up/down the controller */ void azx_power_notify(struct hda_bus *bus) @@ -462,11 +480,18 @@ void azx_power_notify(struct hda_bus *bus) break; } } - if (power_on) + + if (power_on) { + nv_tegra_enable_hda_clks(true); azx_init_chip(chip, 1); - else if (chip->running && power_save_controller && - !bus->power_keep_link_on) - azx_stop_chip(chip); + } + else { + if (chip->running && power_save_controller && + !bus->power_keep_link_on) + azx_stop_chip(chip); + + nv_tegra_enable_hda_clks(false); + } } #endif /* CONFIG_SND_HDA_POWER_SAVE */ @@ -475,15 +500,6 @@ void azx_power_notify(struct hda_bus *bus) /* * power management */ -static int nv_tegra_hda_controller_suspend(struct platform_device *pdev) -{ - clk_disable(clk_hda2hdmicodec); - clk_disable(clk_hda2codec); - clk_disable(clk_hda); - - return 0; -} - static int nv_tegra_azx_suspend(struct platform_device *pdev, pm_message_t state) { @@ -491,26 +507,23 @@ static int nv_tegra_azx_suspend(struct platform_device *pdev, struct azx *chip = card->private_data; int i; + nv_tegra_enable_hda_clks(true); snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); azx_clear_irq_pending(chip); for (i = 0; i < HDA_MAX_PCMS; i++) snd_pcm_suspend_all(chip->pcm[i]); if (chip->initialized) snd_hda_suspend(chip->bus); - azx_stop_chip(chip); + + if (!chip->bus->power_keep_link_on) + azx_stop_chip(chip); + if (chip->irq >= 0) { free_irq(chip->irq, chip); chip->irq = -1; } - return nv_tegra_hda_controller_suspend(pdev); -} - -static int nv_tegra_hda_controller_resume(struct platform_device *pdev) -{ - clk_enable(clk_hda); - clk_enable(clk_hda2codec); - clk_enable(clk_hda2hdmicodec); + nv_tegra_enable_hda_clks(false); return 0; } @@ -519,21 +532,22 @@ static int nv_tegra_azx_resume(struct platform_device *pdev) { struct snd_card *card = dev_get_drvdata(&pdev->dev); struct azx *chip = card->private_data; - int rc; - rc = nv_tegra_hda_controller_resume(pdev); - if (rc) - return rc; + nv_tegra_enable_hda_clks(true); chip->msi = 0; if (azx_acquire_irq(chip, 1) < 0) return -EIO; - if (snd_hda_codecs_inuse(chip->bus)) + if (snd_hda_codecs_inuse(chip->bus) || chip->bus->power_keep_link_on) azx_init_chip(chip, 1); snd_hda_resume(chip->bus); snd_power_change_state(card, SNDRV_CTL_POWER_D0); + + if (!snd_hda_codecs_inuse(chip->bus)) + nv_tegra_enable_hda_clks(false); + return 0; } @@ -783,9 +797,8 @@ static int nv_tegra_hda_controller_init(struct platform_device *pdev) snd_printk(KERN_ERR T30SFX "%s: can't get hda clock\n", __func__); return -1; } - clk_enable(clk_hda); - clk_enable(clk_hda2codec); - clk_enable(clk_hda2hdmicodec); + nv_tegra_enable_hda_clks(true); + /*Enable the PCI access */ temp = readl(hda_reg + IPFS_HDA_CONFIGURATION_0); temp |= IPFS_EN_FPCI; |