[alsa-devel] [PATCH 04/15] ALSA: hda - Add helper to read eld data

Subhransu S. Prusty subhransu.s.prusty at intel.com
Tue Dec 1 18:47:00 CET 2015


The eld reading APIs are required for ASoC skylake hdmi
driver as well. So moving these definition to core. Once
component ops for reading ELD is available will mark this
as deprecated.

Signed-off-by: Subhransu S. Prusty <subhransu.s.prusty at intel.com>
Signed-off-by: Vinod Koul <vinod.koul at intel.com>
---
 include/sound/hdaudio.h |  3 ++
 sound/hda/Makefile      |  2 +-
 sound/hda/hdac_eld.c    | 95 +++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 99 insertions(+), 1 deletion(-)
 create mode 100644 sound/hda/hdac_eld.c

diff --git a/include/sound/hdaudio.h b/include/sound/hdaudio.h
index e2b712c..1170f21 100644
--- a/include/sound/hdaudio.h
+++ b/include/sound/hdaudio.h
@@ -455,6 +455,9 @@ void snd_hdac_stream_sync(struct hdac_stream *azx_dev, bool start,
 			  unsigned int streams);
 void snd_hdac_stream_timecounter_init(struct hdac_stream *azx_dev,
 				      unsigned int streams);
+/* HDMI helpers to query eld from codec */
+int snd_hdac_get_eld(struct hdac_device *codec, hda_nid_t nid,
+		unsigned char *buf, int *eld_size);
 /*
  * macros for easy use
  */
diff --git a/sound/hda/Makefile b/sound/hda/Makefile
index 7e999c9..e0a2b25 100644
--- a/sound/hda/Makefile
+++ b/sound/hda/Makefile
@@ -1,5 +1,5 @@
 snd-hda-core-objs := hda_bus_type.o hdac_bus.o hdac_device.o hdac_sysfs.o \
-	hdac_regmap.o hdac_controller.o hdac_stream.o array.o
+	hdac_regmap.o hdac_controller.o hdac_stream.o array.o hdac_eld.o
 
 snd-hda-core-objs += trace.o
 CFLAGS_trace.o := -I$(src)
diff --git a/sound/hda/hdac_eld.c b/sound/hda/hdac_eld.c
new file mode 100644
index 0000000..9126e0f
--- /dev/null
+++ b/sound/hda/hdac_eld.c
@@ -0,0 +1,95 @@
+/*
+ * HDMI Eld routines
+ */
+
+#include <sound/hdaudio.h>
+
+#define ELD_FIXED_BYTES	20
+#define ELD_MAX_SIZE    256
+
+static unsigned int snd_hdac_get_eld_data(struct hdac_device *codec,
+				hda_nid_t nid, int byte_index)
+{
+	unsigned int val;
+
+	val = snd_hdac_codec_read(codec, nid, 0,
+					AC_VERB_GET_HDMI_ELDD, byte_index);
+
+	dev_dbg(&codec->dev, "HDMI: ELD data byte %d: 0x%x\n", byte_index, val);
+
+	return val;
+}
+
+static int snd_hdac_get_eld_size(struct hdac_device *codec, hda_nid_t nid)
+{
+	return snd_hdac_codec_read(codec, nid, 0, AC_VERB_GET_HDMI_DIP_SIZE,
+						 AC_DIPSIZE_ELD_BUF);
+}
+
+/**
+ * snd_hdac_get_eld - Query eld from sink
+ * @codec - device to query
+ * @nid - codec node to query
+ * @buf - Buffer to fill eld data
+ * @eld_size - Size of eld queried
+ *
+ * Returns zero on success or a negative error code
+ *
+ * This function queries the eld size and eld data and fills in the buffer
+ * passed by user
+ */
+int snd_hdac_get_eld(struct hdac_device *codec, hda_nid_t nid,
+		     unsigned char *buf, int *eld_size)
+{
+	int i;
+	int ret = 0;
+	int size;
+
+	/*
+	 * ELD size is initialized to zero in caller function. If no errors and
+	 * ELD is valid, actual eld_size is assigned.
+	 */
+
+	size = snd_hdac_get_eld_size(codec, nid);
+	if (size == 0) {
+		/* wfg: workaround for ASUS P5E-VM HDMI board */
+		dev_info(&codec->dev, "HDMI: ELD buf size is 0, force 128\n");
+		size = 128;
+	}
+	if (size < ELD_FIXED_BYTES || size > ELD_MAX_SIZE) {
+		dev_info(&codec->dev, "HDMI: invalid ELD buf size %d\n", size);
+		return -ERANGE;
+	}
+
+	/* set ELD buffer */
+	for (i = 0; i < size; i++) {
+		unsigned int val = snd_hdac_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)) {
+			dev_info(&codec->dev, "HDMI: invalid ELD data byte %d\n", i);
+			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) {
+			dev_dbg(&codec->dev, "HDMI: 0 ELD data\n");
+			ret = -EINVAL;
+			goto error;
+		}
+		buf[i] = val;
+	}
+
+	*eld_size = size;
+error:
+	return ret;
+}
+EXPORT_SYMBOL_GPL(snd_hdac_get_eld);
-- 
1.9.1



More information about the Alsa-devel mailing list