diff options
author | Vinod G <vinodg@nvidia.com> | 2016-02-03 13:13:24 -0500 |
---|---|---|
committer | Sameer Pujar <spujar@nvidia.com> | 2017-08-07 05:26:22 -0400 |
commit | 8ef38fea895377cffc9cfcbe73d68fadbe3fd2df (patch) | |
tree | 32fa4e3f09429d4987d333a28a90aec681652396 /sound/pci/hda | |
parent | a33bd5974b506b86b605d15080314ac1b6b08406 (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.c | 48 |
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 | ||
232 | static int hda_tegra_enable_clocks(struct hda_tegra *data) | 235 | static 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 | ||
256 | disable_codec_2x: | 267 | disable_codec_2x: |
257 | clk_disable_unprepare(data->hda2codec_2x_clk); | 268 | clk_disable_unprepare(hda->hda2codec_2x_clk); |
258 | disable_hda: | 269 | disable_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 | ||
265 | static void hda_tegra_disable_clocks(struct hda_tegra *hda) | 277 | static 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) | ||
277 | static int hda_tegra_suspend(struct device *dev) | 298 | static 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) { |