提交 0a673521 编写于 作者: L Lu, Han 提交者: Takashi Iwai

ALSA: hda - reset display codec when power on

In SKL, HDMI/DP codec and PCH HD Audio Controller are in different power wells,
so it's necessary to reset display audio codecs when power well on, otherwise
display audio codecs will disappear when resume from low power state.
Reset steps when power on:
    enable codec wakeup -> azx_init_chip() -> disable codec wakeup

The callback for codec wakeup enable/disable is in drivers/gpu/drm/i915/.
Signed-off-by: NLu, Han <han.lu@intel.com>
Signed-off-by: NTakashi Iwai <tiwai@suse.de>
上级 632f3ab9
...@@ -33,6 +33,27 @@ ...@@ -33,6 +33,27 @@
#define AZX_REG_EM4 0x100c #define AZX_REG_EM4 0x100c
#define AZX_REG_EM5 0x1010 #define AZX_REG_EM5 0x1010
int hda_set_codec_wakeup(struct hda_intel *hda, bool enable)
{
struct i915_audio_component *acomp = &hda->audio_component;
if (!acomp->ops)
return -ENODEV;
if (!acomp->ops->codec_wake_override) {
dev_warn(&hda->chip.pci->dev,
"Invalid codec wake callback\n");
return 0;
}
dev_dbg(&hda->chip.pci->dev, "%s codec wakeup\n",
enable ? "enable" : "disable");
acomp->ops->codec_wake_override(acomp->dev, enable);
return 0;
}
int hda_display_power(struct hda_intel *hda, bool enable) int hda_display_power(struct hda_intel *hda, bool enable)
{ {
struct i915_audio_component *acomp = &hda->audio_component; struct i915_audio_component *acomp = &hda->audio_component;
......
...@@ -491,6 +491,17 @@ static void azx_init_pci(struct azx *chip) ...@@ -491,6 +491,17 @@ static void azx_init_pci(struct azx *chip)
} }
} }
static void hda_intel_init_chip(struct azx *chip, bool full_reset)
{
struct hda_intel *hda = container_of(chip, struct hda_intel, chip);
if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL)
hda_set_codec_wakeup(hda, true);
azx_init_chip(chip, full_reset);
if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL)
hda_set_codec_wakeup(hda, false);
}
/* calculate runtime delay from LPIB */ /* calculate runtime delay from LPIB */
static int azx_get_delay_from_lpib(struct azx *chip, struct azx_dev *azx_dev, static int azx_get_delay_from_lpib(struct azx *chip, struct azx_dev *azx_dev,
unsigned int pos) unsigned int pos)
...@@ -850,7 +861,7 @@ static int azx_resume(struct device *dev) ...@@ -850,7 +861,7 @@ static int azx_resume(struct device *dev)
return -EIO; return -EIO;
azx_init_pci(chip); azx_init_pci(chip);
azx_init_chip(chip, true); hda_intel_init_chip(chip, true);
snd_power_change_state(card, SNDRV_CTL_POWER_D0); snd_power_change_state(card, SNDRV_CTL_POWER_D0);
return 0; return 0;
...@@ -912,13 +923,16 @@ static int azx_runtime_resume(struct device *dev) ...@@ -912,13 +923,16 @@ static int azx_runtime_resume(struct device *dev)
&& hda->need_i915_power) { && hda->need_i915_power) {
hda_display_power(hda, true); hda_display_power(hda, true);
haswell_set_bclk(hda); haswell_set_bclk(hda);
/* toggle codec wakeup bit for STATESTS read */
hda_set_codec_wakeup(hda, true);
hda_set_codec_wakeup(hda, false);
} }
/* Read STATESTS before controller reset */ /* Read STATESTS before controller reset */
status = azx_readw(chip, STATESTS); status = azx_readw(chip, STATESTS);
azx_init_pci(chip); azx_init_pci(chip);
azx_init_chip(chip, true); hda_intel_init_chip(chip, true);
if (status) { if (status) {
list_for_each_codec(codec, &chip->bus) list_for_each_codec(codec, &chip->bus)
...@@ -1629,7 +1643,7 @@ static int azx_first_init(struct azx *chip) ...@@ -1629,7 +1643,7 @@ static int azx_first_init(struct azx *chip)
haswell_set_bclk(hda); haswell_set_bclk(hda);
} }
azx_init_chip(chip, (probe_only[dev] & 2) == 0); hda_intel_init_chip(chip, (probe_only[dev] & 2) == 0);
/* codec detection */ /* codec detection */
if (!azx_bus(chip)->codec_mask) { if (!azx_bus(chip)->codec_mask) {
......
...@@ -51,11 +51,16 @@ struct hda_intel { ...@@ -51,11 +51,16 @@ struct hda_intel {
}; };
#ifdef CONFIG_SND_HDA_I915 #ifdef CONFIG_SND_HDA_I915
int hda_set_codec_wakeup(struct hda_intel *hda, bool enable);
int hda_display_power(struct hda_intel *hda, bool enable); int hda_display_power(struct hda_intel *hda, bool enable);
void haswell_set_bclk(struct hda_intel *hda); void haswell_set_bclk(struct hda_intel *hda);
int hda_i915_init(struct hda_intel *hda); int hda_i915_init(struct hda_intel *hda);
int hda_i915_exit(struct hda_intel *hda); int hda_i915_exit(struct hda_intel *hda);
#else #else
static inline int hda_set_codec_wakeup(struct hda_intel *hda, bool enable)
{
return 0;
}
static inline int hda_display_power(struct hda_intel *hda, bool enable) static inline int hda_display_power(struct hda_intel *hda, bool enable)
{ {
return 0; return 0;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册