aboutsummaryrefslogtreecommitdiffstats
path: root/sound
diff options
context:
space:
mode:
authorDavid Henningsson <david.henningsson@canonical.com>2015-08-19 04:48:58 -0400
committerTakashi Iwai <tiwai@suse.de>2015-09-02 06:24:40 -0400
commit25adc137c546ce297b4d76820913dda11cad3891 (patch)
treed0055d62d7ddc2ad71850de3b12c1b47dc4e60d1 /sound
parent45c053df5bdc4843cf19b920db6ab819ddc27ff7 (diff)
ALSA: hda - Wake the codec up on pin/ELD notify events
Whenever there is an event from the i915 driver, wake the codec and recheck plug/unplug + ELD status. This fixes the issue with lost unsol events in power save mode, the codec and controller can now sleep in D3 and still know when the HDMI monitor has been connected. Signed-off-by: David Henningsson <david.henningsson@canonical.com> Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound')
-rw-r--r--sound/pci/hda/patch_hdmi.c22
1 files changed, 21 insertions, 1 deletions
diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c
index a97db5fc8a15..932292ce5ce7 100644
--- a/sound/pci/hda/patch_hdmi.c
+++ b/sound/pci/hda/patch_hdmi.c
@@ -37,6 +37,8 @@
37#include <sound/jack.h> 37#include <sound/jack.h>
38#include <sound/asoundef.h> 38#include <sound/asoundef.h>
39#include <sound/tlv.h> 39#include <sound/tlv.h>
40#include <sound/hdaudio.h>
41#include <sound/hda_i915.h>
40#include "hda_codec.h" 42#include "hda_codec.h"
41#include "hda_local.h" 43#include "hda_local.h"
42#include "hda_jack.h" 44#include "hda_jack.h"
@@ -144,6 +146,9 @@ struct hdmi_spec {
144 */ 146 */
145 struct hda_multi_out multiout; 147 struct hda_multi_out multiout;
146 struct hda_pcm_stream pcm_playback; 148 struct hda_pcm_stream pcm_playback;
149
150 /* i915/powerwell (Haswell+/Valleyview+) specific */
151 struct i915_audio_component_audio_ops i915_audio_ops;
147}; 152};
148 153
149 154
@@ -2191,6 +2196,9 @@ static void generic_hdmi_free(struct hda_codec *codec)
2191 struct hdmi_spec *spec = codec->spec; 2196 struct hdmi_spec *spec = codec->spec;
2192 int pin_idx; 2197 int pin_idx;
2193 2198
2199 if (is_haswell_plus(codec) || is_valleyview_plus(codec))
2200 snd_hdac_i915_register_notifier(NULL);
2201
2194 for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) { 2202 for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) {
2195 struct hdmi_spec_per_pin *per_pin = get_pin(spec, pin_idx); 2203 struct hdmi_spec_per_pin *per_pin = get_pin(spec, pin_idx);
2196 2204
@@ -2316,6 +2324,14 @@ static void haswell_set_power_state(struct hda_codec *codec, hda_nid_t fg,
2316 snd_hda_codec_set_power_to_all(codec, fg, power_state); 2324 snd_hda_codec_set_power_to_all(codec, fg, power_state);
2317} 2325}
2318 2326
2327static void intel_pin_eld_notify(void *audio_ptr, int port, int port_mst_index)
2328{
2329 struct hda_codec *codec = audio_ptr;
2330 int pin_nid = port + 0x04;
2331
2332 check_presence_and_report(codec, pin_nid);
2333}
2334
2319static int patch_generic_hdmi(struct hda_codec *codec) 2335static int patch_generic_hdmi(struct hda_codec *codec)
2320{ 2336{
2321 struct hdmi_spec *spec; 2337 struct hdmi_spec *spec;
@@ -2342,8 +2358,12 @@ static int patch_generic_hdmi(struct hda_codec *codec)
2342 if (is_valleyview_plus(codec) || is_skylake(codec)) 2358 if (is_valleyview_plus(codec) || is_skylake(codec))
2343 codec->core.link_power_control = 1; 2359 codec->core.link_power_control = 1;
2344 2360
2345 if (is_haswell_plus(codec) || is_valleyview_plus(codec)) 2361 if (is_haswell_plus(codec) || is_valleyview_plus(codec)) {
2346 codec->depop_delay = 0; 2362 codec->depop_delay = 0;
2363 spec->i915_audio_ops.audio_ptr = codec;
2364 spec->i915_audio_ops.pin_eld_notify = intel_pin_eld_notify;
2365 snd_hdac_i915_register_notifier(&spec->i915_audio_ops);
2366 }
2347 2367
2348 if (hdmi_parse_codec(codec) < 0) { 2368 if (hdmi_parse_codec(codec) < 0) {
2349 codec->spec = NULL; 2369 codec->spec = NULL;