aboutsummaryrefslogtreecommitdiffstats
path: root/sound/pci/hda/patch_hdmi.c
diff options
context:
space:
mode:
authorWu Fengguang <fengguang.wu@intel.com>2011-11-16 03:29:47 -0500
committerTakashi Iwai <tiwai@suse.de>2011-11-16 04:44:42 -0500
commit744626dada90cb1231a65b08874aa7a9f11c2ea8 (patch)
treeaf45566be0dd278ed698f00deb1b734ad0b492d3 /sound/pci/hda/patch_hdmi.c
parentb95d68b8179764e29558b75cec35ef4a6a98925b (diff)
ALSA: hda - delayed ELD repoll
The Intel HDMI chips (ironlake at least) are found to have ~250ms delay between the ELD_Valid=1 hotplug event is send and the ELD buffer becomes actually readable. During the time the ELD buffer is mysteriously all 0. Fix it by scheduling a delayed work to re-read ELD buffer after 300ms. Signed-off-by: Wu Fengguang <fengguang.wu@intel.com> Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/pci/hda/patch_hdmi.c')
-rw-r--r--sound/pci/hda/patch_hdmi.c36
1 files changed, 29 insertions, 7 deletions
diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c
index aebfee50bd88..a76139b60154 100644
--- a/sound/pci/hda/patch_hdmi.c
+++ b/sound/pci/hda/patch_hdmi.c
@@ -65,7 +65,10 @@ struct hdmi_spec_per_pin {
65 hda_nid_t pin_nid; 65 hda_nid_t pin_nid;
66 int num_mux_nids; 66 int num_mux_nids;
67 hda_nid_t mux_nids[HDA_MAX_CONNECTIONS]; 67 hda_nid_t mux_nids[HDA_MAX_CONNECTIONS];
68
69 struct hda_codec *codec;
68 struct hdmi_eld sink_eld; 70 struct hdmi_eld sink_eld;
71 struct delayed_work work;
69}; 72};
70 73
71struct hdmi_spec { 74struct hdmi_spec {
@@ -745,8 +748,7 @@ static void hdmi_setup_audio_infoframe(struct hda_codec *codec, int pin_idx,
745 * Unsolicited events 748 * Unsolicited events
746 */ 749 */
747 750
748static void hdmi_present_sense(struct hda_codec *codec, hda_nid_t pin_nid, 751static void hdmi_present_sense(struct hdmi_spec_per_pin *per_pin, bool retry);
749 struct hdmi_eld *eld);
750 752
751static void hdmi_intrinsic_event(struct hda_codec *codec, unsigned int res) 753static void hdmi_intrinsic_event(struct hda_codec *codec, unsigned int res)
752{ 754{
@@ -766,7 +768,7 @@ static void hdmi_intrinsic_event(struct hda_codec *codec, unsigned int res)
766 return; 768 return;
767 eld = &spec->pins[pin_idx].sink_eld; 769 eld = &spec->pins[pin_idx].sink_eld;
768 770
769 hdmi_present_sense(codec, pin_nid, eld); 771 hdmi_present_sense(&spec->pins[pin_idx], true);
770 772
771 /* 773 /*
772 * HDMI sink's ELD info cannot always be retrieved for now, e.g. 774 * HDMI sink's ELD info cannot always be retrieved for now, e.g.
@@ -968,9 +970,11 @@ static int hdmi_read_pin_conn(struct hda_codec *codec, int pin_idx)
968 return 0; 970 return 0;
969} 971}
970 972
971static void hdmi_present_sense(struct hda_codec *codec, hda_nid_t pin_nid, 973static void hdmi_present_sense(struct hdmi_spec_per_pin *per_pin, bool retry)
972 struct hdmi_eld *eld)
973{ 974{
975 struct hda_codec *codec = per_pin->codec;
976 struct hdmi_eld *eld = &per_pin->sink_eld;
977 hda_nid_t pin_nid = per_pin->pin_nid;
974 /* 978 /*
975 * Always execute a GetPinSense verb here, even when called from 979 * Always execute a GetPinSense verb here, even when called from
976 * hdmi_intrinsic_event; for some NVIDIA HW, the unsolicited 980 * hdmi_intrinsic_event; for some NVIDIA HW, the unsolicited
@@ -992,13 +996,27 @@ static void hdmi_present_sense(struct hda_codec *codec, hda_nid_t pin_nid,
992 "HDMI status: Codec=%d Pin=%d Presence_Detect=%d ELD_Valid=%d\n", 996 "HDMI status: Codec=%d Pin=%d Presence_Detect=%d ELD_Valid=%d\n",
993 codec->addr, pin_nid, eld->monitor_present, eld_valid); 997 codec->addr, pin_nid, eld->monitor_present, eld_valid);
994 998
995 if (eld_valid) 999 if (eld_valid) {
996 if (!snd_hdmi_get_eld(eld, codec, pin_nid)) 1000 if (!snd_hdmi_get_eld(eld, codec, pin_nid))
997 snd_hdmi_show_eld(eld); 1001 snd_hdmi_show_eld(eld);
1002 else if (retry) {
1003 queue_delayed_work(codec->bus->workq,
1004 &per_pin->work,
1005 msecs_to_jiffies(300));
1006 }
1007 }
998 1008
999 snd_hda_input_jack_report(codec, pin_nid); 1009 snd_hda_input_jack_report(codec, pin_nid);
1000} 1010}
1001 1011
1012static void hdmi_repoll_eld(struct work_struct *work)
1013{
1014 struct hdmi_spec_per_pin *per_pin =
1015 container_of(to_delayed_work(work), struct hdmi_spec_per_pin, work);
1016
1017 hdmi_present_sense(per_pin, false);
1018}
1019
1002static int hdmi_add_pin(struct hda_codec *codec, hda_nid_t pin_nid) 1020static int hdmi_add_pin(struct hda_codec *codec, hda_nid_t pin_nid)
1003{ 1021{
1004 struct hdmi_spec *spec = codec->spec; 1022 struct hdmi_spec *spec = codec->spec;
@@ -1227,7 +1245,7 @@ static int generic_hdmi_build_jack(struct hda_codec *codec, int pin_idx)
1227 if (err < 0) 1245 if (err < 0)
1228 return err; 1246 return err;
1229 1247
1230 hdmi_present_sense(codec, per_pin->pin_nid, &per_pin->sink_eld); 1248 hdmi_present_sense(per_pin, false);
1231 return 0; 1249 return 0;
1232} 1250}
1233 1251
@@ -1278,6 +1296,8 @@ static int generic_hdmi_init(struct hda_codec *codec)
1278 AC_VERB_SET_UNSOLICITED_ENABLE, 1296 AC_VERB_SET_UNSOLICITED_ENABLE,
1279 AC_USRSP_EN | pin_nid); 1297 AC_USRSP_EN | pin_nid);
1280 1298
1299 per_pin->codec = codec;
1300 INIT_DELAYED_WORK(&per_pin->work, hdmi_repoll_eld);
1281 snd_hda_eld_proc_new(codec, eld, pin_idx); 1301 snd_hda_eld_proc_new(codec, eld, pin_idx);
1282 } 1302 }
1283 return 0; 1303 return 0;
@@ -1292,10 +1312,12 @@ static void generic_hdmi_free(struct hda_codec *codec)
1292 struct hdmi_spec_per_pin *per_pin = &spec->pins[pin_idx]; 1312 struct hdmi_spec_per_pin *per_pin = &spec->pins[pin_idx];
1293 struct hdmi_eld *eld = &per_pin->sink_eld; 1313 struct hdmi_eld *eld = &per_pin->sink_eld;
1294 1314
1315 cancel_delayed_work(&per_pin->work);
1295 snd_hda_eld_proc_free(codec, eld); 1316 snd_hda_eld_proc_free(codec, eld);
1296 } 1317 }
1297 snd_hda_input_jack_free(codec); 1318 snd_hda_input_jack_free(codec);
1298 1319
1320 flush_workqueue(codec->bus->workq);
1299 kfree(spec); 1321 kfree(spec);
1300} 1322}
1301 1323