diff options
author | Takashi Iwai <tiwai@suse.de> | 2013-11-07 07:38:23 -0500 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2013-11-07 08:02:49 -0500 |
commit | efe4710860fa6ed10dd041f13902f0e06c86e8cc (patch) | |
tree | 5cfecea529d1e8650d51cc841d1959b417253ba8 /sound/pci/hda | |
parent | 3b098eb486868d57d7f2666d05b86c19a07df71b (diff) |
ALSA: hda - Delay HDMI presence reports while waiting for ELD information
There is a small gap between the jack detection unsolicited event and
the time the ELD is updated. When user-space queries the HDMI ELD
immediately after receiving the notification, it might fail because of
this gap.
For avoiding such a problem, this patch tries to delay the HDMI jack
detect notification until ELD information is fully updated. The
workaround is imperfect, but good enough as a starting point.
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/pci/hda')
-rw-r--r-- | sound/pci/hda/patch_hdmi.c | 17 |
1 files changed, 12 insertions, 5 deletions
diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index e22323f50424..ce412d1a15d0 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c | |||
@@ -1140,7 +1140,7 @@ static void hdmi_setup_audio_infoframe(struct hda_codec *codec, | |||
1140 | * Unsolicited events | 1140 | * Unsolicited events |
1141 | */ | 1141 | */ |
1142 | 1142 | ||
1143 | static void hdmi_present_sense(struct hdmi_spec_per_pin *per_pin, int repoll); | 1143 | static bool hdmi_present_sense(struct hdmi_spec_per_pin *per_pin, int repoll); |
1144 | 1144 | ||
1145 | static void hdmi_intrinsic_event(struct hda_codec *codec, unsigned int res) | 1145 | static void hdmi_intrinsic_event(struct hda_codec *codec, unsigned int res) |
1146 | { | 1146 | { |
@@ -1166,8 +1166,8 @@ static void hdmi_intrinsic_event(struct hda_codec *codec, unsigned int res) | |||
1166 | if (pin_idx < 0) | 1166 | if (pin_idx < 0) |
1167 | return; | 1167 | return; |
1168 | 1168 | ||
1169 | hdmi_present_sense(get_pin(spec, pin_idx), 1); | 1169 | if (hdmi_present_sense(get_pin(spec, pin_idx), 1)) |
1170 | snd_hda_jack_report_sync(codec); | 1170 | snd_hda_jack_report_sync(codec); |
1171 | } | 1171 | } |
1172 | 1172 | ||
1173 | static void hdmi_non_intrinsic_event(struct hda_codec *codec, unsigned int res) | 1173 | static void hdmi_non_intrinsic_event(struct hda_codec *codec, unsigned int res) |
@@ -1475,7 +1475,7 @@ static int hdmi_read_pin_conn(struct hda_codec *codec, int pin_idx) | |||
1475 | return 0; | 1475 | return 0; |
1476 | } | 1476 | } |
1477 | 1477 | ||
1478 | static void hdmi_present_sense(struct hdmi_spec_per_pin *per_pin, int repoll) | 1478 | static bool hdmi_present_sense(struct hdmi_spec_per_pin *per_pin, int repoll) |
1479 | { | 1479 | { |
1480 | struct hda_codec *codec = per_pin->codec; | 1480 | struct hda_codec *codec = per_pin->codec; |
1481 | struct hdmi_spec *spec = codec->spec; | 1481 | struct hdmi_spec *spec = codec->spec; |
@@ -1493,6 +1493,7 @@ static void hdmi_present_sense(struct hdmi_spec_per_pin *per_pin, int repoll) | |||
1493 | int present = snd_hda_pin_sense(codec, pin_nid); | 1493 | int present = snd_hda_pin_sense(codec, pin_nid); |
1494 | bool update_eld = false; | 1494 | bool update_eld = false; |
1495 | bool eld_changed = false; | 1495 | bool eld_changed = false; |
1496 | bool ret; | ||
1496 | 1497 | ||
1497 | mutex_lock(&per_pin->lock); | 1498 | mutex_lock(&per_pin->lock); |
1498 | pin_eld->monitor_present = !!(present & AC_PINSENSE_PRESENCE); | 1499 | pin_eld->monitor_present = !!(present & AC_PINSENSE_PRESENCE); |
@@ -1559,7 +1560,12 @@ static void hdmi_present_sense(struct hdmi_spec_per_pin *per_pin, int repoll) | |||
1559 | SNDRV_CTL_EVENT_MASK_VALUE | SNDRV_CTL_EVENT_MASK_INFO, | 1560 | SNDRV_CTL_EVENT_MASK_VALUE | SNDRV_CTL_EVENT_MASK_INFO, |
1560 | &per_pin->eld_ctl->id); | 1561 | &per_pin->eld_ctl->id); |
1561 | unlock: | 1562 | unlock: |
1563 | if ((codec->vendor_id & 0xffff0000) == 0x10020000) | ||
1564 | ret = true; /* AMD codecs create ELD by itself */ | ||
1565 | else | ||
1566 | ret = !repoll || !pin_eld->monitor_present || pin_eld->eld_valid; | ||
1562 | mutex_unlock(&per_pin->lock); | 1567 | mutex_unlock(&per_pin->lock); |
1568 | return ret; | ||
1563 | } | 1569 | } |
1564 | 1570 | ||
1565 | static void hdmi_repoll_eld(struct work_struct *work) | 1571 | static void hdmi_repoll_eld(struct work_struct *work) |
@@ -1570,7 +1576,8 @@ static void hdmi_repoll_eld(struct work_struct *work) | |||
1570 | if (per_pin->repoll_count++ > 6) | 1576 | if (per_pin->repoll_count++ > 6) |
1571 | per_pin->repoll_count = 0; | 1577 | per_pin->repoll_count = 0; |
1572 | 1578 | ||
1573 | hdmi_present_sense(per_pin, per_pin->repoll_count); | 1579 | if (hdmi_present_sense(per_pin, per_pin->repoll_count)) |
1580 | snd_hda_jack_report_sync(per_pin->codec); | ||
1574 | } | 1581 | } |
1575 | 1582 | ||
1576 | static void intel_haswell_fixup_connect_list(struct hda_codec *codec, | 1583 | static void intel_haswell_fixup_connect_list(struct hda_codec *codec, |