summaryrefslogtreecommitdiff
path: root/sound/pci/hda/hda_intel.c
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2015-04-29 12:28:52 +0200
committerTakashi Iwai <tiwai@suse.de>2015-04-29 12:28:52 +0200
commit85abf3ec5fa663c9638ef2d10d9623880a26458e (patch)
treece1cc6166cd34b4a49299ccf4aefaac657a34fcf /sound/pci/hda/hda_intel.c
parent49c4a4c5244d2c1a25ec1e01dbb4fba3813d237d (diff)
parent2bd1f73f4242ee19d8c610bcffe6e7a813451ce0 (diff)
Merge branch 'topic/hda' into for-next
Diffstat (limited to 'sound/pci/hda/hda_intel.c')
-rw-r--r--sound/pci/hda/hda_intel.c46
1 files changed, 38 insertions, 8 deletions
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
index c212f13e1721..5aa5cfa517aa 100644
--- a/sound/pci/hda/hda_intel.c
+++ b/sound/pci/hda/hda_intel.c
@@ -543,6 +543,14 @@ static int azx_position_check(struct azx *chip, struct azx_dev *azx_dev)
return 0;
}
+/* Enable/disable i915 display power for the link */
+static int azx_intel_link_power(struct azx *chip, bool enable)
+{
+ struct hda_intel *hda = container_of(chip, struct hda_intel, chip);
+
+ return hda_display_power(hda, enable);
+}
+
/*
* Check whether the current DMA position is acceptable for updating
* periods. Returns non-zero if it's OK.
@@ -809,7 +817,8 @@ static int azx_suspend(struct device *dev)
if (chip->msi)
pci_disable_msi(chip->pci);
- if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL)
+ if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL
+ && hda->need_i915_power)
hda_display_power(hda, false);
return 0;
}
@@ -829,7 +838,8 @@ static int azx_resume(struct device *dev)
if (chip->disabled || hda->init_failed)
return 0;
- if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL) {
+ if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL
+ && hda->need_i915_power) {
hda_display_power(hda, true);
haswell_set_bclk(hda);
}
@@ -872,7 +882,8 @@ static int azx_runtime_suspend(struct device *dev)
azx_stop_chip(chip);
azx_enter_link_reset(chip);
azx_clear_irq_pending(chip);
- if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL)
+ if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL
+ && hda->need_i915_power)
hda_display_power(hda, false);
return 0;
@@ -897,7 +908,8 @@ static int azx_runtime_resume(struct device *dev)
if (!azx_has_pm_runtime(chip))
return 0;
- if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL) {
+ if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL
+ && hda->need_i915_power) {
hda_display_power(hda, true);
haswell_set_bclk(hda);
}
@@ -1118,7 +1130,8 @@ static int azx_free(struct azx *chip)
release_firmware(chip->fw);
#endif
if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL) {
- hda_display_power(hda, false);
+ if (hda->need_i915_power)
+ hda_display_power(hda, false);
hda_i915_exit(hda);
}
kfree(hda);
@@ -1789,6 +1802,7 @@ static const struct hda_controller_ops pci_hda_ops = {
.substream_free_pages = substream_free_pages,
.pcm_mmap_prepare = pcm_mmap_prepare,
.position_check = azx_position_check,
+ .link_power = azx_intel_link_power,
};
static int azx_probe(struct pci_dev *pci,
@@ -1882,17 +1896,28 @@ static int azx_probe_continue(struct azx *chip)
int err;
hda->probe_continued = 1;
- /* Request power well for Haswell HDA controller and codec */
+
+ /* Request display power well for the HDA controller or codec. For
+ * Haswell/Broadwell, both the display HDA controller and codec need
+ * this power. For other platforms, like Baytrail/Braswell, only the
+ * display codec needs the power and it can be released after probe.
+ */
if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL) {
+ /* Baytral/Braswell controllers don't need this power */
+ if (pci->device != 0x0f04 && pci->device != 0x2284)
+ hda->need_i915_power = 1;
+
+
#ifdef CONFIG_SND_HDA_I915
err = hda_i915_init(hda);
if (err < 0)
- goto out_free;
+ goto i915_power_fail;
+
err = hda_display_power(hda, true);
if (err < 0) {
dev_err(chip->card->dev,
"Cannot turn on display power on i915\n");
- goto out_free;
+ goto i915_power_fail;
}
#endif
}
@@ -1939,6 +1964,11 @@ static int azx_probe_continue(struct azx *chip)
pm_runtime_put_noidle(&pci->dev);
out_free:
+ if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL
+ && !hda->need_i915_power)
+ hda_display_power(hda, false);
+
+i915_power_fail:
if (err < 0)
hda->init_failed = 1;
complete_all(&hda->probe_wait);