diff options
author | Alan Tull <alan.tull@freescale.com> | 2011-11-02 12:57:55 -0500 |
---|---|---|
committer | Alan Tull <alan.tull@freescale.com> | 2011-11-02 13:40:03 -0500 |
commit | 4a4fe22000b376e0bcc1d3bd09d727b46b256a1b (patch) | |
tree | 3446b35e9fb217b86e0773fe1473764c12853c78 /sound | |
parent | 43190a7b58b679a740bd7c30e206ca5151f77b86 (diff) |
ENGR00161288 balance spdif clock enables and disables
Add tx_active, rx_active flags to keep track of what channels
have enabled clocks.
In suspend/resume, only disable/re-enable the clocks that were
enabled.
Signed-off-by: Alan Tull <alan.tull@freescale.com>
Diffstat (limited to 'sound')
-rw-r--r-- | sound/soc/codecs/mxc_spdif.c | 34 |
1 files changed, 30 insertions, 4 deletions
diff --git a/sound/soc/codecs/mxc_spdif.c b/sound/soc/codecs/mxc_spdif.c index 56eac29c54c5..e275735faa05 100644 --- a/sound/soc/codecs/mxc_spdif.c +++ b/sound/soc/codecs/mxc_spdif.c @@ -72,6 +72,8 @@ struct mxc_spdif_priv { struct snd_card *card; /* ALSA SPDIF sound card handle */ struct snd_pcm *pcm; /* ALSA spdif driver type handle */ atomic_t dpll_locked; /* DPLL locked status */ + bool tx_active; + bool rx_active; }; struct spdif_mixer_control mxc_spdif_control; @@ -506,6 +508,7 @@ static int mxc_spdif_playback_startup(struct snd_pcm_substream *substream, if (!plat_data->spdif_tx) return -EINVAL; + spdif_priv->tx_active = true; clk_enable(plat_data->spdif_clk); clk_enable(plat_data->spdif_audio_clk); @@ -521,7 +524,9 @@ static int mxc_spdif_playback_startup(struct snd_pcm_substream *substream, return 0; failed: + clk_disable(plat_data->spdif_audio_clk); clk_disable(plat_data->spdif_clk); + spdif_priv->tx_active = false; return err; } @@ -610,6 +615,7 @@ static int mxc_spdif_playback_shutdown(struct snd_pcm_substream *substream, clk_disable(plat_data->spdif_audio_clk); clk_disable(plat_data->spdif_clk); + spdif_priv->tx_active = false; return 0; } @@ -626,6 +632,8 @@ static int mxc_spdif_capture_startup(struct snd_pcm_substream *substream, if (!plat_data->spdif_rx) return -EINVAL; + spdif_priv->rx_active = true; + /* enable rx bus clock */ clk_enable(plat_data->spdif_clk); @@ -648,6 +656,7 @@ static int mxc_spdif_capture_startup(struct snd_pcm_substream *substream, failed: clk_disable(plat_data->spdif_clk); + spdif_priv->rx_active = false; return err; } @@ -727,6 +736,7 @@ static int mxc_spdif_capture_shutdown(struct snd_pcm_substream *substream, __raw_writel(regval, spdif_base_addr + SPDIF_REG_SCR); clk_disable(plat_data->spdif_clk); + spdif_priv->rx_active = false; return 0; } @@ -1117,7 +1127,15 @@ static int mxc_spdif_soc_suspend(struct snd_soc_codec *codec, return -EINVAL; plat_data = spdif_priv->plat_data; - clk_disable(plat_data->spdif_clk); + + if (spdif_priv->tx_active) { + clk_disable(plat_data->spdif_audio_clk); + clk_disable(plat_data->spdif_clk); + } + + if (spdif_priv->rx_active) + clk_disable(plat_data->spdif_clk); + clk_disable(plat_data->spdif_core_clk); return 0; @@ -1134,7 +1152,15 @@ static int mxc_spdif_soc_resume(struct snd_soc_codec *codec) plat_data = spdif_priv->plat_data; clk_enable(plat_data->spdif_core_clk); - clk_enable(plat_data->spdif_clk); + + if (spdif_priv->tx_active) { + clk_enable(plat_data->spdif_clk); + clk_enable(plat_data->spdif_audio_clk); + } + + if (spdif_priv->rx_active) + clk_enable(plat_data->spdif_clk); + spdif_softreset(); return 0; @@ -1196,6 +1222,8 @@ static int __devinit mxc_spdif_probe(struct platform_device *pdev) mxc_spdif_codec_dai.capture.formats = MXC_SPDIF_FORMATS_CAPTURE; } + spdif_priv->tx_active = false; + spdif_priv->rx_active = false; platform_set_drvdata(pdev, spdif_priv); spdif_priv->reg_phys_base = res->start; @@ -1250,7 +1278,6 @@ static int __devinit mxc_spdif_probe(struct platform_device *pdev) return 0; card_err: - clk_disable(plat_data->spdif_clk); clk_put(plat_data->spdif_clk); clk_disable(plat_data->spdif_core_clk); @@ -1267,7 +1294,6 @@ static int __devexit mxc_spdif_remove(struct platform_device *pdev) snd_soc_unregister_codec(&pdev->dev); - clk_disable(plat_data->spdif_clk); clk_put(plat_data->spdif_clk); clk_disable(plat_data->spdif_core_clk); |