aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sound/soc/codecs/mxc_spdif.c34
1 files changed, 30 insertions, 4 deletions
diff --git a/sound/soc/codecs/mxc_spdif.c b/sound/soc/codecs/mxc_spdif.c
index 56eac29c54c..e275735faa0 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);