summaryrefslogtreecommitdiffstats
path: root/sound/pci/hda
diff options
context:
space:
mode:
authorVinod G <vinodg@nvidia.com>2016-02-03 13:13:24 -0500
committerSameer Pujar <spujar@nvidia.com>2017-08-07 05:26:22 -0400
commit8ef38fea895377cffc9cfcbe73d68fadbe3fd2df (patch)
tree32fa4e3f09429d4987d333a28a90aec681652396 /sound/pci/hda
parenta33bd5974b506b86b605d15080314ac1b6b08406 (diff)
ALSA: HDA: Fix for SC7 hang.
Make sure the powergate/ungate are matched and be called with clk_on and clk_off function call. Change-Id: Ie49a0974a2d31c48c963f55fcba0369a5b29d688 Signed-off-by: Vinod G <vinodg@nvidia.com> Signed-off-by: Mohan Kumar <mkumard@nvidia.com> Reviewed-on: http://git-master/r/1002511 Reviewed-by: Automatic_Commit_Validation_User GVS: Gerrit_Virtual_Submit Reviewed-by: Prashant Gaikwad <pgaikwad@nvidia.com> Tested-by: Prashant Gaikwad <pgaikwad@nvidia.com> Reviewed-by: Ravindra Lokhande <rlokhande@nvidia.com>
Diffstat (limited to 'sound/pci/hda')
-rw-r--r--sound/pci/hda/hda_tegra.c48
1 files changed, 35 insertions, 13 deletions
diff --git a/sound/pci/hda/hda_tegra.c b/sound/pci/hda/hda_tegra.c
index 931c98f7a..6032b7b86 100644
--- a/sound/pci/hda/hda_tegra.c
+++ b/sound/pci/hda/hda_tegra.c
@@ -2,6 +2,8 @@
2 * 2 *
3 * Implementation of primary ALSA driver code base for NVIDIA Tegra HDA. 3 * Implementation of primary ALSA driver code base for NVIDIA Tegra HDA.
4 * 4 *
5 * Copyright (c) 2014-2016, NVIDIA CORPORATION, All rights reserved.
6 *
5 * This program is free software; you can redistribute it and/or modify it 7 * This program is free software; you can redistribute it and/or modify it
6 * under the terms and conditions of the GNU General Public License, 8 * under the terms and conditions of the GNU General Public License,
7 * version 2, as published by the Free Software Foundation. 9 * version 2, as published by the Free Software Foundation.
@@ -93,6 +95,7 @@ struct hda_tegra {
93 struct reset_control *hda2codec_2x_rst; 95 struct reset_control *hda2codec_2x_rst;
94 struct reset_control *hda2hdmi_rst; 96 struct reset_control *hda2hdmi_rst;
95#endif 97#endif
98 bool is_power_on;
96}; 99};
97 100
98#ifdef CONFIG_PM 101#ifdef CONFIG_PM
@@ -229,51 +232,69 @@ static void hda_tegra_init(struct hda_tegra *hda)
229 writel(v, hda->regs + HDA_IPFS_INTR_MASK); 232 writel(v, hda->regs + HDA_IPFS_INTR_MASK);
230} 233}
231 234
232static int hda_tegra_enable_clocks(struct hda_tegra *data) 235static int hda_tegra_enable_clocks(struct hda_tegra *hda)
233{ 236{
234 int rc; 237 int rc;
235 238
236 tegra_unpowergate_partition(data->partition_id); 239 if (hda->is_power_on == false) {
240#if !defined(CONFIG_ARCH_TEGRA_18x_SOC)
241 tegra_unpowergate_partition(hda->partition_id);
242#else
243 tegra_unpowergate_partition_with_clk_on(
244 hda->partition_id);
245#endif
246 hda->is_power_on = true;
247 }
237 248
238#if defined(CONFIG_COMMON_CLK) 249#if defined(CONFIG_COMMON_CLK)
239 reset_control_reset(data->hda_rst); 250 reset_control_reset(hda->hda_rst);
240 reset_control_reset(data->hda2codec_2x_rst); 251 reset_control_reset(hda->hda2codec_2x_rst);
241 reset_control_reset(data->hda2hdmi_rst); 252 reset_control_reset(hda->hda2hdmi_rst);
242#endif 253#endif
243 254
244 rc = clk_prepare_enable(data->hda_clk); 255 rc = clk_prepare_enable(hda->hda_clk);
245 if (rc) 256 if (rc)
246 return rc; 257 return rc;
247 rc = clk_prepare_enable(data->hda2codec_2x_clk); 258 rc = clk_prepare_enable(hda->hda2codec_2x_clk);
248 if (rc) 259 if (rc)
249 goto disable_hda; 260 goto disable_hda;
250 rc = clk_prepare_enable(data->hda2hdmi_clk); 261 rc = clk_prepare_enable(hda->hda2hdmi_clk);
251 if (rc) 262 if (rc)
252 goto disable_codec_2x; 263 goto disable_codec_2x;
253 264
254 return 0; 265 return 0;
255 266
256disable_codec_2x: 267disable_codec_2x:
257 clk_disable_unprepare(data->hda2codec_2x_clk); 268 clk_disable_unprepare(hda->hda2codec_2x_clk);
258disable_hda: 269disable_hda:
259 clk_disable_unprepare(data->hda_clk); 270 clk_disable_unprepare(hda->hda_clk);
260 tegra_powergate_partition(data->partition_id); 271 if (hda->is_power_on)
272 tegra_powergate_partition(hda->partition_id);
273 hda->is_power_on = false;
261 return rc; 274 return rc;
262} 275}
263 276
264#ifdef CONFIG_PM_SLEEP
265static void hda_tegra_disable_clocks(struct hda_tegra *hda) 277static void hda_tegra_disable_clocks(struct hda_tegra *hda)
266{ 278{
267 clk_disable_unprepare(hda->hda2hdmi_clk); 279 clk_disable_unprepare(hda->hda2hdmi_clk);
268 clk_disable_unprepare(hda->hda2codec_2x_clk); 280 clk_disable_unprepare(hda->hda2codec_2x_clk);
269 clk_disable_unprepare(hda->hda_clk); 281 clk_disable_unprepare(hda->hda_clk);
270 282
271 tegra_powergate_partition(hda->partition_id); 283 if (hda->is_power_on) {
284#if !defined(CONFIG_ARCH_TEGRA_18x_SOC)
285 tegra_powergate_partition(hda->partition_id);
286#else
287 tegra_powergate_partition_with_clk_off(
288 hda->partition_id);
289#endif
290 hda->is_power_on = false;
291 }
272} 292}
273 293
274/* 294/*
275 * power management 295 * power management
276 */ 296 */
297#if defined(CONFIG_PM_SLEEP) || defined(CONFIG_SUSPEND)
277static int hda_tegra_suspend(struct device *dev) 298static int hda_tegra_suspend(struct device *dev)
278{ 299{
279 struct snd_card *card = dev_get_drvdata(dev); 300 struct snd_card *card = dev_get_drvdata(dev);
@@ -606,6 +627,7 @@ static int hda_tegra_probe(struct platform_device *pdev)
606 return -ENOMEM; 627 return -ENOMEM;
607 hda->dev = &pdev->dev; 628 hda->dev = &pdev->dev;
608 chip = &hda->chip; 629 chip = &hda->chip;
630 hda->is_power_on = false;
609 631
610 hda->partition_id = tegra_pd_get_powergate_id(tegra_disb_pd); 632 hda->partition_id = tegra_pd_get_powergate_id(tegra_disb_pd);
611 if (hda->partition_id < 0) { 633 if (hda->partition_id < 0) {