summaryrefslogtreecommitdiff
path: root/sound/soc/tegra/tegra_wm8903.c
diff options
context:
space:
mode:
authorSumit Bhattacharya <sumitb@nvidia.com>2011-11-11 20:46:33 +0530
committerDan Willemsen <dwillemsen@nvidia.com>2011-11-30 21:50:05 -0800
commitf15ba4f7d9e4ecf598ca31d25afbb00685990346 (patch)
treec487e3adb889a61c9c7749bdd3c5b834fa62aae6 /sound/soc/tegra/tegra_wm8903.c
parent2a2ee828caf46de70b044187c7d718fcc2b84770 (diff)
ASoC: Tegra: Tegra machine: Improve clk management logic
Use tegra asoc util lock_rate API to lock pll_a, pll_a_out and mclk settings whenever any DAI-link using these clocks is active. If any dai-link fails to set clock due to another active dai-link it will check if the current mclk rate is acceptable for it's purpose before erroring out. Also add hw_param ops for SPDIF dai-link. Bug 872652 Change-Id: I6ef1a3b69745bdf85cb88f5fbccfb05c37e33c5d Signed-off-by: Sumit Bhattacharya <sumitb@nvidia.com> Reviewed-on: http://git-master/r/63856 Reviewed-by: Varun Colbert <vcolbert@nvidia.com> Rebase-Id: Rdf4d19ce1ff150dd5835c891dfed0cea16150016
Diffstat (limited to 'sound/soc/tegra/tegra_wm8903.c')
-rw-r--r--sound/soc/tegra/tegra_wm8903.c71
1 files changed, 68 insertions, 3 deletions
diff --git a/sound/soc/tegra/tegra_wm8903.c b/sound/soc/tegra/tegra_wm8903.c
index a260ac85d6f2..8ef9da6e2789 100644
--- a/sound/soc/tegra/tegra_wm8903.c
+++ b/sound/soc/tegra/tegra_wm8903.c
@@ -94,10 +94,16 @@ static int tegra_wm8903_hw_params(struct snd_pcm_substream *substream,
err = tegra_asoc_utils_set_rate(&machine->util_data, srate, mclk);
if (err < 0) {
- dev_err(card->dev, "Can't configure clocks\n");
- return err;
+ if (!(machine->util_data.set_mclk % mclk))
+ mclk = machine->util_data.set_mclk;
+ else {
+ dev_err(card->dev, "Can't configure clocks\n");
+ return err;
+ }
}
+ tegra_asoc_utils_lock_clk_rate(&machine->util_data, 1);
+
i2s_daifmt = SND_SOC_DAIFMT_NB_NF |
SND_SOC_DAIFMT_CBS_CFS;
@@ -131,11 +137,70 @@ static int tegra_wm8903_hw_params(struct snd_pcm_substream *substream,
return 0;
}
+static int tegra_spdif_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_card *card = rtd->card;
+ struct tegra_wm8903 *machine = snd_soc_card_get_drvdata(card);
+ int srate, mclk, min_mclk;
+ int err;
+
+ srate = params_rate(params);
+ switch (srate) {
+ case 11025:
+ case 22050:
+ case 44100:
+ case 88200:
+ mclk = 11289600;
+ break;
+ case 8000:
+ case 16000:
+ case 32000:
+ case 48000:
+ case 64000:
+ case 96000:
+ mclk = 12288000;
+ break;
+ default:
+ return -EINVAL;
+ }
+ min_mclk = 128 * srate;
+
+ err = tegra_asoc_utils_set_rate(&machine->util_data, srate, mclk);
+ if (err < 0) {
+ if (!(machine->util_data.set_mclk % min_mclk))
+ mclk = machine->util_data.set_mclk;
+ else {
+ dev_err(card->dev, "Can't configure clocks\n");
+ return err;
+ }
+ }
+
+ tegra_asoc_utils_lock_clk_rate(&machine->util_data, 1);
+
+ return 0;
+}
+
+static int tegra_hw_free(struct snd_pcm_substream *substream)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct tegra_wm8903 *machine = snd_soc_card_get_drvdata(rtd->card);
+
+ tegra_asoc_utils_lock_clk_rate(&machine->util_data, 0);
+
+ return 0;
+}
+
static struct snd_soc_ops tegra_wm8903_ops = {
.hw_params = tegra_wm8903_hw_params,
+ .hw_free = tegra_hw_free,
};
-static struct snd_soc_ops tegra_spdif_ops;
+static struct snd_soc_ops tegra_spdif_ops = {
+ .hw_params = tegra_spdif_hw_params,
+ .hw_free = tegra_hw_free,
+};
static struct snd_soc_jack tegra_wm8903_hp_jack;