ALSA: hda - fail ELD reading early
[pandora-kernel.git] / sound / pci / hda / hda_eld.c
index 1c8ddf5..c1da422 100644 (file)
@@ -297,10 +297,18 @@ static int hdmi_update_eld(struct hdmi_eld *e,
                                        buf + ELD_FIXED_BYTES + mnl + 3 * i);
        }
 
+       /*
+        * HDMI sink's ELD info cannot always be retrieved for now, e.g.
+        * in console or for audio devices. Assume the highest speakers
+        * configuration, to _not_ prohibit multi-channel audio playback.
+        */
+       if (!e->spk_alloc)
+               e->spk_alloc = 0xffff;
+
+       e->eld_valid = true;
        return 0;
 
 out_fail:
-       e->eld_ver = 0;
        return -EINVAL;
 }
 
@@ -323,9 +331,6 @@ int snd_hdmi_get_eld(struct hdmi_eld *eld,
         * ELD is valid, actual eld_size is assigned in hdmi_update_eld()
         */
 
-       if (!eld->eld_valid)
-               return -ENOENT;
-
        size = snd_hdmi_get_eld_size(codec, nid);
        if (size == 0) {
                /* wfg: workaround for ASUS P5E-VM HDMI board */
@@ -342,18 +347,28 @@ int snd_hdmi_get_eld(struct hdmi_eld *eld,
 
        for (i = 0; i < size; i++) {
                unsigned int val = hdmi_get_eld_data(codec, nid, i);
+               /*
+                * Graphics driver might be writing to ELD buffer right now.
+                * Just abort. The caller will repoll after a while.
+                */
                if (!(val & AC_ELDD_ELD_VALID)) {
-                       if (!i) {
-                               snd_printd(KERN_INFO
-                                          "HDMI: invalid ELD data\n");
-                               ret = -EINVAL;
-                               goto error;
-                       }
                        snd_printd(KERN_INFO
                                  "HDMI: invalid ELD data byte %d\n", i);
-                       val = 0;
-               } else
-                       val &= AC_ELDD_ELD_DATA;
+                       ret = -EINVAL;
+                       goto error;
+               }
+               val &= AC_ELDD_ELD_DATA;
+               /*
+                * The first byte cannot be zero. This can happen on some DVI
+                * connections. Some Intel chips may also need some 250ms delay
+                * to return non-zero ELD data, even when the graphics driver
+                * correctly writes ELD content before setting ELD_valid bit.
+                */
+               if (!val && !i) {
+                       snd_printdd(KERN_INFO "HDMI: 0 ELD data\n");
+                       ret = -EINVAL;
+                       goto error;
+               }
                buf[i] = val;
        }