[igt-dev] [PATCH i-g-t 3/3] lib/igt_kms: introduce igt_kms_get_hdmi_audio_edid

Simon Ser simon.ser at intel.com
Mon May 27 12:03:07 UTC 2019


This new function uses igt_edid to generate an EDID suitable for testing HDMI
audio. It's imported from kms_chamelium with minor edits, it's used there and
in kms_hdmi_inject. A (unexported for now) generate_hdmi_audio_edid function
enables generation of EDIDs with arbitrary SAD and speaker blocks.

This obsoletes kmstest_edid_add_audio.

The sanity check for the HDMI audio EDID has been moved from
lib/tests/igt_hdmi_inject.c to lib/tests/igt_edid.c.

Signed-off-by: Simon Ser <simon.ser at intel.com>
---
 lib/igt_kms.c               | 133 ++++++++++++++++++++----------------
 lib/igt_kms.h               |  10 ++-
 lib/tests/igt_edid.c        |   1 +
 lib/tests/igt_hdmi_inject.c |   1 -
 tests/kms_chamelium.c       |  62 +----------------
 tests/kms_hdmi_inject.c     |   9 ++-
 6 files changed, 88 insertions(+), 128 deletions(-)

diff --git a/lib/igt_kms.c b/lib/igt_kms.c
index a7dc3ac3fb66..d7d711a72d27 100644
--- a/lib/igt_kms.c
+++ b/lib/igt_kms.c
@@ -26,6 +26,8 @@
  */
 
 #include "config.h"
+
+#include <assert.h>
 #include <inttypes.h>
 #include <unistd.h>
 #include <stdio.h>
@@ -180,6 +182,79 @@ const unsigned char *igt_kms_get_alt_edid(void)
 	return (unsigned char *) &edid;
 }
 
+static void
+generate_hdmi_audio_edid(unsigned char raw_edid[static HDMI_AUDIO_EDID_LENGTH],
+			 struct cea_sad *sad,
+			 struct cea_speaker_alloc *speaker_alloc)
+{
+	struct edid *edid;
+	struct edid_ext *edid_ext;
+	struct edid_cea *edid_cea;
+	char *cea_data;
+	struct edid_cea_data_block *block;
+	const struct cea_vsd *vsd;
+	size_t cea_data_size, vsd_size;
+
+	/* Create a new EDID from the base IGT EDID, and add an
+	 * extension that advertises audio support. */
+	edid = (struct edid *) raw_edid;
+	memcpy(edid, igt_kms_get_base_edid(), sizeof(struct edid));
+	edid->extensions_len = 1;
+	edid_ext = &edid->extensions[0];
+	edid_cea = &edid_ext->data.cea;
+	cea_data = edid_cea->data;
+	cea_data_size = 0;
+
+	/* Short Audio Descriptor block */
+	block = (struct edid_cea_data_block *) &cea_data[cea_data_size];
+	cea_data_size += edid_cea_data_block_set_sad(block, sad, 1);
+
+	/* A Vendor Specific Data block is needed for HDMI audio */
+	block = (struct edid_cea_data_block *) &cea_data[cea_data_size];
+	vsd = cea_vsd_get_hdmi_default(&vsd_size);
+	cea_data_size += edid_cea_data_block_set_vsd(block, vsd,
+						     vsd_size);
+
+	/* Speaker Allocation Data block */
+	block = (struct edid_cea_data_block *) &cea_data[cea_data_size];
+	cea_data_size += edid_cea_data_block_set_speaker_alloc(block,
+							       speaker_alloc);
+
+	assert(cea_data_size <= sizeof(edid_cea->data));
+
+	edid_ext_set_cea(edid_ext, cea_data_size,
+			 EDID_CEA_BASIC_AUDIO);
+
+	edid_update_checksum(edid);
+	edid_ext_update_cea_checksum(edid_ext);
+}
+
+const unsigned char *igt_kms_get_hdmi_audio_edid(void)
+{
+	int channels;
+	uint8_t sampling_rates, sample_sizes;
+	static unsigned char raw_edid[HDMI_AUDIO_EDID_LENGTH] = {0};
+	struct cea_sad sad = {0};
+	struct cea_speaker_alloc speaker_alloc = {0};
+
+	/* Initialize the Short Audio Descriptor for PCM */
+	channels = 2;
+	sampling_rates = CEA_SAD_SAMPLING_RATE_32KHZ |
+			 CEA_SAD_SAMPLING_RATE_44KHZ |
+			 CEA_SAD_SAMPLING_RATE_48KHZ;
+	sample_sizes = CEA_SAD_SAMPLE_SIZE_16 |
+		       CEA_SAD_SAMPLE_SIZE_20 |
+		       CEA_SAD_SAMPLE_SIZE_24;
+	cea_sad_init_pcm(&sad, channels, sampling_rates, sample_sizes);
+
+	/* Initialize the Speaker Allocation Data */
+	speaker_alloc.speakers = CEA_SPEAKER_FRONT_LEFT_RIGHT_CENTER;
+
+	generate_hdmi_audio_edid(raw_edid, &sad, &speaker_alloc);
+
+	return raw_edid;
+}
+
 const char * const igt_plane_prop_names[IGT_NUM_PLANE_PROPS] = {
 	[IGT_PLANE_SRC_X] = "SRC_X",
 	[IGT_PLANE_SRC_Y] = "SRC_Y",
@@ -1356,64 +1431,6 @@ void kmstest_edid_add_4k(const unsigned char *edid, size_t length,
 	update_edid_csum(new_edid.data, length);
 }
 
-/**
- * kmstest_edid_add_audio:
- * @edid: an existing valid edid block
- * @length: length of @edid
- * @new_edid_ptr: pointer to where the new edid will be placed
- * @new_length: pointer to the size of the new edid
- *
- * Makes a copy of an existing edid block and adds an extension indicating
- * basic audio support and speaker data block.
- *
- */
-void kmstest_edid_add_audio(const unsigned char *edid, size_t length,
-			    unsigned char *new_edid_ptr[], size_t *new_length)
-{
-	char vsdb_block_len = 10, audio_block_len = 4, spkr_block_len = 4;
-	struct edid_block new_edid = init_cea_block(edid, length, new_edid_ptr,
-						    new_length,
-						    vsdb_block_len +
-						    audio_block_len +
-						    spkr_block_len,
-						    DTD_SUPPORTS_AUDIO);
-	int pos = new_edid.pos;
-
-	/* audio block, short audio block descriptors  */
-	new_edid.data[pos++] = (1 << 5) | (audio_block_len - 1);
-	new_edid.data[pos++] = 0x09; /* Audio Format, PCM */
-	new_edid.data[pos++] = 0x07; /* Frequency, 32, 44.1, 48kHz  */
-	new_edid.data[pos++] = 0x07; /* Bit Rate 16, 20, 24 bit */
-
-
-	/* vsdb block ( id | length ) -- need vsdb as well
-	 * otherwise the kernel will fallback to lower clock modes */
-	new_edid.data[pos++] = 3 << 5 | (vsdb_block_len - 1);
-	/* registration id */
-	new_edid.data[pos++] = 0x3;
-	new_edid.data[pos++] = 0xc;
-	new_edid.data[pos++] = 0x0;
-	/* source physical address */
-	new_edid.data[pos++] = 0x10;
-	new_edid.data[pos++] = 0x00;
-	/* Supports_AI ... etc */
-	new_edid.data[pos++] = 0x00;
-	/* Max TMDS Clock */
-	new_edid.data[pos++] = 0x00;
-	/* Latency present, HDMI Video Present */
-	new_edid.data[pos++] = 0x20;
-	/* HDMI Video */
-	new_edid.data[pos++] = 0x00; /* 3D present */
-
-	/* speaker data block */
-	new_edid.data[pos++] = (4 << 5) | (spkr_block_len - 1);
-	new_edid.data[pos++] = (1 << 5);
-	new_edid.data[pos++] = 0x00;
-	new_edid.data[pos++] = 0x00;
-
-	update_edid_csum(new_edid.data, length);
-}
-
 /**
  * kmstest_unset_all_crtcs:
  * @drm_fd: the DRM fd
diff --git a/lib/igt_kms.h b/lib/igt_kms.h
index 38bdc08f3d50..4ac28131b6d9 100644
--- a/lib/igt_kms.h
+++ b/lib/igt_kms.h
@@ -196,7 +196,6 @@ bool kmstest_force_connector(int fd, drmModeConnector *connector,
 			     enum kmstest_force_connector_state state);
 void kmstest_edid_add_3d(const unsigned char *edid, size_t length, unsigned char *new_edid_ptr[], size_t *new_length);
 void kmstest_edid_add_4k(const unsigned char *edid, size_t length, unsigned char *new_edid_ptr[], size_t *new_length);
-void kmstest_edid_add_audio(const unsigned char *edid, size_t length, unsigned char *new_edid_ptr[], size_t *new_length);
 void kmstest_force_edid(int drm_fd, drmModeConnector *connector,
 			const unsigned char *edid, size_t length);
 
@@ -754,9 +753,14 @@ void igt_reset_connectors(void);
 
 uint32_t kmstest_get_vbl_flag(uint32_t pipe_id);
 
+struct cea_sad;
+struct cea_speaker_alloc;
+
 #define EDID_LENGTH 128
-const unsigned char* igt_kms_get_base_edid(void);
-const unsigned char* igt_kms_get_alt_edid(void);
+#define HDMI_AUDIO_EDID_LENGTH (2 * EDID_LENGTH)
+const unsigned char *igt_kms_get_base_edid(void);
+const unsigned char *igt_kms_get_alt_edid(void);
+const unsigned char *igt_kms_get_hdmi_audio_edid(void);
 
 struct udev_monitor *igt_watch_hotplug(void);
 bool igt_hotplug_detected(struct udev_monitor *mon,
diff --git a/lib/tests/igt_edid.c b/lib/tests/igt_edid.c
index 6cf6b5c14b53..a847df272525 100644
--- a/lib/tests/igt_edid.c
+++ b/lib/tests/igt_edid.c
@@ -75,6 +75,7 @@ igt_simple_main
 	} funcs[] = {
 		{ "base", igt_kms_get_base_edid, 0 },
 		{ "alt", igt_kms_get_alt_edid, 0 },
+		{ "hdmi_audio", igt_kms_get_hdmi_audio_edid, 1 },
 		{0},
 	}, *f;
 	const unsigned char *edid;
diff --git a/lib/tests/igt_hdmi_inject.c b/lib/tests/igt_hdmi_inject.c
index 9b6780a14aa6..2534b1a23acb 100644
--- a/lib/tests/igt_hdmi_inject.c
+++ b/lib/tests/igt_hdmi_inject.c
@@ -73,7 +73,6 @@ igt_simple_main
 	} funcs[] = {
 		{ "3D", kmstest_edid_add_3d },
 		{ "4k", kmstest_edid_add_4k },
-		{ "audio", kmstest_edid_add_audio },
 		{ NULL, NULL },
 	}, *f;
 
diff --git a/tests/kms_chamelium.c b/tests/kms_chamelium.c
index 8da6ec20759e..e75786d33765 100644
--- a/tests/kms_chamelium.c
+++ b/tests/kms_chamelium.c
@@ -1740,66 +1740,6 @@ test_hpd_storm_disable(data_t *data, struct chamelium_port *port, int width)
 	igt_hpd_storm_reset(data->drm_fd);
 }
 
-#define HDMI_AUDIO_EDID_SIZE (sizeof(struct edid) + sizeof(struct edid_ext))
-
-static unsigned const char *get_hdmi_audio_edid(void)
-{
-	int channels;
-	uint8_t sampling_rates, sample_sizes;
-	static unsigned char raw_edid[HDMI_AUDIO_EDID_SIZE] = {0};
-	struct edid *edid;
-	struct edid_ext *edid_ext;
-	struct edid_cea *edid_cea;
-	char *cea_data;
-	struct edid_cea_data_block *block;
-	struct cea_sad sad = {0};
-	const struct cea_vsd *vsd;
-	size_t cea_data_size, vsd_size;
-
-	/* Initialize the Short Audio Descriptor for PCM */
-	channels = 2; /* TODO: speaker alloc blocks for > 2 channels */
-	sampling_rates = CEA_SAD_SAMPLING_RATE_32KHZ |
-			 CEA_SAD_SAMPLING_RATE_44KHZ |
-			 CEA_SAD_SAMPLING_RATE_48KHZ |
-			 CEA_SAD_SAMPLING_RATE_88KHZ |
-			 CEA_SAD_SAMPLING_RATE_96KHZ |
-			 CEA_SAD_SAMPLING_RATE_176KHZ |
-			 CEA_SAD_SAMPLING_RATE_192KHZ;
-	sample_sizes = CEA_SAD_SAMPLE_SIZE_16 |
-		       CEA_SAD_SAMPLE_SIZE_20 |
-		       CEA_SAD_SAMPLE_SIZE_24;
-	cea_sad_init_pcm(&sad, channels, sampling_rates, sample_sizes);
-
-	/* Create a new EDID from the base IGT EDID, and add an
-	 * extension that advertises audio support. */
-	edid = (struct edid *) raw_edid;
-	memcpy(edid, igt_kms_get_base_edid(), sizeof(struct edid));
-	edid->extensions_len = 1;
-	edid_ext = &edid->extensions[0];
-	edid_cea = &edid_ext->data.cea;
-	cea_data = edid_cea->data;
-	cea_data_size = 0;
-
-	block = (struct edid_cea_data_block *) &cea_data[cea_data_size];
-	cea_data_size += edid_cea_data_block_set_sad(block, &sad, 1);
-
-	/* A Vendor Specific Data block is needed for HDMI audio */
-	block = (struct edid_cea_data_block *) &cea_data[cea_data_size];
-	vsd = cea_vsd_get_hdmi_default(&vsd_size);
-	cea_data_size += edid_cea_data_block_set_vsd(block, vsd,
-						     vsd_size);
-
-	igt_assert(cea_data_size <= sizeof(edid_cea->data));
-
-	edid_ext_set_cea(edid_ext, cea_data_size,
-			 EDID_CEA_BASIC_AUDIO);
-
-	edid_update_checksum(edid);
-	edid_ext_update_cea_checksum(edid_ext);
-
-	return raw_edid;
-}
-
 static const unsigned char *get_edid(enum test_edid edid)
 {
 	switch (edid) {
@@ -1811,7 +1751,7 @@ static const unsigned char *get_edid(enum test_edid edid)
 	case TEST_EDID_ALT:
 		return igt_kms_get_alt_edid();
 	case TEST_EDID_HDMI_AUDIO:
-		return get_hdmi_audio_edid();
+		return igt_kms_get_hdmi_audio_edid();
 	}
 	assert(0); /* unreachable */
 }
diff --git a/tests/kms_hdmi_inject.c b/tests/kms_hdmi_inject.c
index a24061042c20..47f5ef2c558a 100644
--- a/tests/kms_hdmi_inject.c
+++ b/tests/kms_hdmi_inject.c
@@ -24,6 +24,7 @@
 
 #include <dirent.h>
 #include "igt.h"
+#include "igt_edid.h"
 
 #define HDISPLAY_4K	3840
 #define VDISPLAY_4K	2160
@@ -211,14 +212,14 @@ eld_is_valid(void)
 static void
 hdmi_inject_audio(int drm_fd, drmModeConnector *connector)
 {
-	unsigned char *edid;
+	const unsigned char *edid;
 	size_t length;
 	int fb_id, cid, ret, crtc_mask = -1;
 	struct igt_fb fb;
 	struct kmstest_connector_config config;
 
-	kmstest_edid_add_audio(igt_kms_get_base_edid(), EDID_LENGTH, &edid,
-			       &length);
+	edid = igt_kms_get_hdmi_audio_edid();
+	length = HDMI_AUDIO_EDID_LENGTH;
 
 	kmstest_force_edid(drm_fd, connector, edid, length);
 
@@ -261,8 +262,6 @@ hdmi_inject_audio(int drm_fd, drmModeConnector *connector)
 
 	kmstest_force_connector(drm_fd, connector, FORCE_CONNECTOR_UNSPECIFIED);
 	kmstest_force_edid(drm_fd, connector, NULL, 0);
-
-	free(edid);
 }
 
 igt_main
-- 
2.21.0



More information about the igt-dev mailing list