|
@@ -543,6 +543,14 @@ static int azx_position_check(struct azx *chip, struct azx_dev *azx_dev)
|
|
return 0;
|
|
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
|
|
* Check whether the current DMA position is acceptable for updating
|
|
* periods. Returns non-zero if it's OK.
|
|
* periods. Returns non-zero if it's OK.
|
|
@@ -809,7 +817,8 @@ static int azx_suspend(struct device *dev)
|
|
|
|
|
|
if (chip->msi)
|
|
if (chip->msi)
|
|
pci_disable_msi(chip->pci);
|
|
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);
|
|
hda_display_power(hda, false);
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
@@ -829,7 +838,8 @@ static int azx_resume(struct device *dev)
|
|
if (chip->disabled || hda->init_failed)
|
|
if (chip->disabled || hda->init_failed)
|
|
return 0;
|
|
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);
|
|
hda_display_power(hda, true);
|
|
haswell_set_bclk(hda);
|
|
haswell_set_bclk(hda);
|
|
}
|
|
}
|
|
@@ -872,7 +882,8 @@ static int azx_runtime_suspend(struct device *dev)
|
|
azx_stop_chip(chip);
|
|
azx_stop_chip(chip);
|
|
azx_enter_link_reset(chip);
|
|
azx_enter_link_reset(chip);
|
|
azx_clear_irq_pending(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);
|
|
hda_display_power(hda, false);
|
|
|
|
|
|
return 0;
|
|
return 0;
|
|
@@ -897,7 +908,8 @@ static int azx_runtime_resume(struct device *dev)
|
|
if (!azx_has_pm_runtime(chip))
|
|
if (!azx_has_pm_runtime(chip))
|
|
return 0;
|
|
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);
|
|
hda_display_power(hda, true);
|
|
haswell_set_bclk(hda);
|
|
haswell_set_bclk(hda);
|
|
}
|
|
}
|
|
@@ -1118,7 +1130,8 @@ static int azx_free(struct azx *chip)
|
|
release_firmware(chip->fw);
|
|
release_firmware(chip->fw);
|
|
#endif
|
|
#endif
|
|
if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL) {
|
|
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);
|
|
hda_i915_exit(hda);
|
|
}
|
|
}
|
|
kfree(hda);
|
|
kfree(hda);
|
|
@@ -1789,6 +1802,7 @@ static const struct hda_controller_ops pci_hda_ops = {
|
|
.substream_free_pages = substream_free_pages,
|
|
.substream_free_pages = substream_free_pages,
|
|
.pcm_mmap_prepare = pcm_mmap_prepare,
|
|
.pcm_mmap_prepare = pcm_mmap_prepare,
|
|
.position_check = azx_position_check,
|
|
.position_check = azx_position_check,
|
|
|
|
+ .link_power = azx_intel_link_power,
|
|
};
|
|
};
|
|
|
|
|
|
static int azx_probe(struct pci_dev *pci,
|
|
static int azx_probe(struct pci_dev *pci,
|
|
@@ -1882,17 +1896,28 @@ static int azx_probe_continue(struct azx *chip)
|
|
int err;
|
|
int err;
|
|
|
|
|
|
hda->probe_continued = 1;
|
|
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) {
|
|
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
|
|
#ifdef CONFIG_SND_HDA_I915
|
|
err = hda_i915_init(hda);
|
|
err = hda_i915_init(hda);
|
|
if (err < 0)
|
|
if (err < 0)
|
|
- goto out_free;
|
|
|
|
|
|
+ goto i915_power_fail;
|
|
|
|
+
|
|
err = hda_display_power(hda, true);
|
|
err = hda_display_power(hda, true);
|
|
if (err < 0) {
|
|
if (err < 0) {
|
|
dev_err(chip->card->dev,
|
|
dev_err(chip->card->dev,
|
|
"Cannot turn on display power on i915\n");
|
|
"Cannot turn on display power on i915\n");
|
|
- goto out_free;
|
|
|
|
|
|
+ goto i915_power_fail;
|
|
}
|
|
}
|
|
#endif
|
|
#endif
|
|
}
|
|
}
|
|
@@ -1939,6 +1964,11 @@ static int azx_probe_continue(struct azx *chip)
|
|
pm_runtime_put_noidle(&pci->dev);
|
|
pm_runtime_put_noidle(&pci->dev);
|
|
|
|
|
|
out_free:
|
|
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)
|
|
if (err < 0)
|
|
hda->init_failed = 1;
|
|
hda->init_failed = 1;
|
|
complete_all(&hda->probe_wait);
|
|
complete_all(&hda->probe_wait);
|