public inbox for igt-dev@lists.freedesktop.org
 help / color / mirror / Atom feed
From: Simon Ser <simon.ser@intel.com>
To: igt-dev@lists.freedesktop.org
Cc: Martin Peres <martin.peres@intel.com>
Subject: [igt-dev] [PATCH i-g-t 3/7] tests/kms_chamelium: generate an EDID with audio support
Date: Fri, 26 Apr 2019 19:21:06 +0300	[thread overview]
Message-ID: <20190426162110.1768-4-simon.ser@intel.com> (raw)
In-Reply-To: <20190426162110.1768-1-simon.ser@intel.com>

The default Chamelium EDID works great with DisplayPort but has issues with
HDMI. The EDID advertises itself as a DisplayPort-only device, which causes
issues with HDMI audio. Additionally, the EDID doesn't contain a magic
incantation within a vendor-specific data block that is needed for audio to
work.

This patch makes it so an EDID is generated and set by IGT. The EDID is the
base IGT EDID patched to append a Short Audio Descriptor and Vendor Specific
Data block extension.

This generated is suitable for HDMI audio. For DisplayPort audio, we keep using
the Chamelium's default EDID.

The global variable holding the test frequencies has been renamed to prevent
shadowing local variables.

Signed-off-by: Simon Ser <simon.ser@intel.com>
---
 lib/igt_chamelium.c   |   9 +++-
 tests/kms_chamelium.c | 123 ++++++++++++++++++++++++++++++------------
 2 files changed, 95 insertions(+), 37 deletions(-)

diff --git a/lib/igt_chamelium.c b/lib/igt_chamelium.c
index ffc68f35..44445444 100644
--- a/lib/igt_chamelium.c
+++ b/lib/igt_chamelium.c
@@ -38,6 +38,7 @@
 #include "igt_chamelium.h"
 #include "igt_core.h"
 #include "igt_aux.h"
+#include "igt_edid.h"
 #include "igt_frame.h"
 #include "igt_list.h"
 #include "igt_kms.h"
@@ -499,14 +500,18 @@ void chamelium_schedule_hpd_toggle(struct chamelium *chamelium,
  *
  * Returns: The ID of the EDID uploaded to the chamelium.
  */
-int chamelium_new_edid(struct chamelium *chamelium, const unsigned char *edid)
+int chamelium_new_edid(struct chamelium *chamelium,
+		       const unsigned char *raw_edid)
 {
 	xmlrpc_value *res;
 	struct chamelium_edid *allocated_edid;
 	int edid_id;
+	struct edid *edid = (struct edid *) raw_edid;
+	size_t edid_size = sizeof(struct edid) +
+			   edid->extensions_len * sizeof(struct edid_ext);
 
 	res = chamelium_rpc(chamelium, NULL, "CreateEdid", "(6)",
-			    edid, EDID_LENGTH);
+			    raw_edid, edid_size);
 
 	xmlrpc_read_int(&chamelium->env, res, &edid_id);
 	xmlrpc_DECREF(res);
diff --git a/tests/kms_chamelium.c b/tests/kms_chamelium.c
index 714e5e06..126af226 100644
--- a/tests/kms_chamelium.c
+++ b/tests/kms_chamelium.c
@@ -27,6 +27,7 @@
 #include "config.h"
 #include "igt.h"
 #include "igt_vc4.h"
+#include "igt_edid.h"
 
 #include <fcntl.h>
 #include <pthread.h>
@@ -414,8 +415,7 @@ test_suspend_resume_edid_change(data_t *data, struct chamelium_port *port,
 }
 
 static igt_output_t *
-prepare_output(data_t *data,
-	       struct chamelium_port *port, bool set_edid)
+prepare_output(data_t *data, struct chamelium_port *port, int edid_id)
 {
 	igt_display_t *display = &data->display;
 	igt_output_t *output;
@@ -428,10 +428,10 @@ prepare_output(data_t *data,
 	igt_require(res = drmModeGetResources(data->drm_fd));
 
 	/* The chamelium's default EDID has a lot of resolutions, way more then
-	 * we need to test
+	 * we need to test. Additionally the default EDID doesn't support HDMI
+	 * audio.
 	 */
-	if (set_edid)
-		chamelium_port_set_edid(data->chamelium, port, data->edid_id);
+	chamelium_port_set_edid(data->chamelium, port, edid_id);
 
 	chamelium_plug(data->chamelium, port);
 	wait_for_connector(data, port, DRM_MODE_CONNECTED);
@@ -616,7 +616,7 @@ static void test_display_one_mode(data_t *data, struct chamelium_port *port,
 
 	reset_state(data, port);
 
-	output = prepare_output(data, port, true);
+	output = prepare_output(data, port, data->edid_id);
 	connector = chamelium_port_get_connector(data->chamelium, port, false);
 	primary = igt_output_get_plane_type(output, DRM_PLANE_TYPE_PRIMARY);
 	igt_assert(primary);
@@ -647,7 +647,7 @@ static void test_display_all_modes(data_t *data, struct chamelium_port *port,
 
 	reset_state(data, port);
 
-	output = prepare_output(data, port, true);
+	output = prepare_output(data, port, data->edid_id);
 	connector = chamelium_port_get_connector(data->chamelium, port, false);
 	primary = igt_output_get_plane_type(output, DRM_PLANE_TYPE_PRIMARY);
 	igt_assert(primary);
@@ -682,7 +682,7 @@ test_display_frame_dump(data_t *data, struct chamelium_port *port)
 
 	reset_state(data, port);
 
-	output = prepare_output(data, port, true);
+	output = prepare_output(data, port, data->edid_id);
 	connector = chamelium_port_get_connector(data->chamelium, port, false);
 	primary = igt_output_get_plane_type(output, DRM_PLANE_TYPE_PRIMARY);
 	igt_assert(primary);
@@ -725,7 +725,7 @@ test_display_frame_dump(data_t *data, struct chamelium_port *port)
 /* A streak of 3 gives confidence that the signal is good. */
 #define MIN_STREAK 3
 
-static int sampling_rates[] = {
+static int test_sampling_rates[] = {
 	32000,
 	44100,
 	48000,
@@ -735,7 +735,7 @@ static int sampling_rates[] = {
 	192000,
 };
 
-static int sampling_rates_count = sizeof(sampling_rates) / sizeof(int);
+static int test_sampling_rates_count = sizeof(test_sampling_rates) / sizeof(int);
 
 static int test_frequencies[] = {
 	300,
@@ -986,7 +986,7 @@ do_test_display_audio(data_t *data, struct chamelium_port *port,
 
 static void
 test_display_audio(data_t *data, struct chamelium_port *port,
-		   const char *audio_device)
+		   const char *audio_device, int edid_id)
 {
 	bool run = false;
 	struct alsa *alsa;
@@ -1005,10 +1005,7 @@ test_display_audio(data_t *data, struct chamelium_port *port,
 
 	reset_state(data, port);
 
-	/* Use the default Chamelium EDID for this test, as the base IGT EDID
-	 * doesn't advertise audio support (see drm_detect_monitor_audio in
-	 * the kernel tree). */
-	output = prepare_output(data, port, false);
+	output = prepare_output(data, port, edid_id);
 	connector = chamelium_port_get_connector(data->chamelium, port, false);
 	primary = igt_output_get_plane_type(output, DRM_PLANE_TYPE_PRIMARY);
 	igt_assert(primary);
@@ -1027,14 +1024,14 @@ test_display_audio(data_t *data, struct chamelium_port *port,
 
 	enable_output(data, port, output, mode, &fb);
 
-	for (i = 0; i < sampling_rates_count; i++) {
+	for (i = 0; i < test_sampling_rates_count; i++) {
 		ret = alsa_open_output(alsa, audio_device);
 		igt_assert(ret >= 0);
 
 		/* TODO: playback on all 8 available channels */
 		run |= do_test_display_audio(data, port, alsa,
 					     PLAYBACK_CHANNELS,
-					     sampling_rates[i]);
+					     test_sampling_rates[i]);
 
 		alsa_close_output(alsa);
 	}
@@ -1377,7 +1374,7 @@ static void test_display_planes_random(data_t *data,
 	reset_state(data, port);
 
 	/* Find the connector and pipe. */
-	output = prepare_output(data, port, true);
+	output = prepare_output(data, port, data->edid_id);
 
 	mode = igt_output_get_mode(output);
 
@@ -1557,7 +1554,17 @@ static data_t data;
 igt_main
 {
 	struct chamelium_port *port;
-	int edid_id, alt_edid_id, p;
+	int p, channels;
+	uint8_t sampling_rates, sample_sizes;
+	char raw_edid[sizeof(struct edid) + sizeof(struct edid_ext)] = {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;
 
 	igt_fixture {
 		igt_skip_on_simulation();
@@ -1569,12 +1576,52 @@ igt_main
 		data.ports = chamelium_get_ports(data.chamelium,
 						 &data.port_count);
 
-		edid_id = chamelium_new_edid(data.chamelium,
-					     igt_kms_get_base_edid());
-		alt_edid_id = chamelium_new_edid(data.chamelium,
+		/* 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);
+
+		data.edid_id = chamelium_new_edid(data.chamelium,
+						  (unsigned char *) raw_edid);
+
+		data.alt_edid_id = chamelium_new_edid(data.chamelium,
 						 igt_kms_get_alt_edid());
-		data.edid_id = edid_id;
-		data.alt_edid_id = alt_edid_id;
 
 		/* So fbcon doesn't try to reprobe things itself */
 		kmstest_set_vt_graphics_mode();
@@ -1598,9 +1645,9 @@ igt_main
 					   HPD_TOGGLE_COUNT_FAST);
 
 		connector_subtest("dp-edid-read", DisplayPort) {
-			test_edid_read(&data, port, edid_id,
+			test_edid_read(&data, port, data.edid_id,
 				       igt_kms_get_base_edid());
-			test_edid_read(&data, port, alt_edid_id,
+			test_edid_read(&data, port, data.alt_edid_id,
 				       igt_kms_get_alt_edid());
 		}
 
@@ -1626,13 +1673,15 @@ igt_main
 			test_suspend_resume_edid_change(&data, port,
 							SUSPEND_STATE_MEM,
 							SUSPEND_TEST_NONE,
-							edid_id, alt_edid_id);
+							data.edid_id,
+							data.alt_edid_id);
 
 		connector_subtest("dp-edid-change-during-hibernate", DisplayPort)
 			test_suspend_resume_edid_change(&data, port,
 							SUSPEND_STATE_DISK,
 							SUSPEND_TEST_DEVICES,
-							edid_id, alt_edid_id);
+							data.edid_id,
+							data.alt_edid_id);
 
 		connector_subtest("dp-crc-single", DisplayPort)
 			test_display_all_modes(&data, port, DRM_FORMAT_XRGB8888,
@@ -1649,8 +1698,10 @@ igt_main
 		connector_subtest("dp-frame-dump", DisplayPort)
 			test_display_frame_dump(&data, port);
 
+		/* The EDID we generate advertises HDMI audio, not DP audio.
+		 * Use the Chamelium's default EDID for DP audio. */
 		connector_subtest("dp-audio", DisplayPort)
-			test_display_audio(&data, port, "HDMI");
+			test_display_audio(&data, port, "HDMI", 0);
 	}
 
 	igt_subtest_group {
@@ -1668,9 +1719,9 @@ igt_main
 					   HPD_TOGGLE_COUNT_FAST);
 
 		connector_subtest("hdmi-edid-read", HDMIA) {
-			test_edid_read(&data, port, edid_id,
+			test_edid_read(&data, port, data.edid_id,
 				       igt_kms_get_base_edid());
-			test_edid_read(&data, port, alt_edid_id,
+			test_edid_read(&data, port, data.alt_edid_id,
 				       igt_kms_get_alt_edid());
 		}
 
@@ -1696,13 +1747,15 @@ igt_main
 			test_suspend_resume_edid_change(&data, port,
 							SUSPEND_STATE_MEM,
 							SUSPEND_TEST_NONE,
-							edid_id, alt_edid_id);
+							data.edid_id,
+							data.alt_edid_id);
 
 		connector_subtest("hdmi-edid-change-during-hibernate", HDMIA)
 			test_suspend_resume_edid_change(&data, port,
 							SUSPEND_STATE_DISK,
 							SUSPEND_TEST_DEVICES,
-							edid_id, alt_edid_id);
+							data.edid_id,
+							data.alt_edid_id);
 
 		connector_subtest("hdmi-crc-single", HDMIA)
 			test_display_all_modes(&data, port, DRM_FORMAT_XRGB8888,
@@ -1813,9 +1866,9 @@ igt_main
 			test_basic_hotplug(&data, port, HPD_TOGGLE_COUNT_FAST);
 
 		connector_subtest("vga-edid-read", VGA) {
-			test_edid_read(&data, port, edid_id,
+			test_edid_read(&data, port, data.edid_id,
 				       igt_kms_get_base_edid());
-			test_edid_read(&data, port, alt_edid_id,
+			test_edid_read(&data, port, data.alt_edid_id,
 				       igt_kms_get_alt_edid());
 		}
 
-- 
2.21.0

_______________________________________________
igt-dev mailing list
igt-dev@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/igt-dev

  parent reply	other threads:[~2019-04-26 16:21 UTC|newest]

Thread overview: 12+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-04-26 16:21 [igt-dev] [PATCH i-g-t 0/7] tests/kms_chamelium: add hdmi-audio test Simon Ser
2019-04-26 16:21 ` [igt-dev] [PATCH i-g-t 1/7] lib/igt_edid: add support for Short Audio Descriptors Simon Ser
2019-04-26 16:21 ` [igt-dev] [PATCH i-g-t 2/7] lib/igt_edid: add support for Vendor Specific Data blocks Simon Ser
2019-04-26 16:21 ` Simon Ser [this message]
2019-05-10 11:35   ` [igt-dev] [PATCH i-g-t 3/7] tests/kms_chamelium: generate an EDID with audio support Arkadiusz Hiler
2019-04-26 16:21 ` [igt-dev] [PATCH i-g-t 4/7] test/kms_chamelium: disable >48KHz audio tests Simon Ser
2019-04-26 16:21 ` [igt-dev] [PATCH i-g-t 5/7] tests/kms_chamelium: enable audio test on HDMI ports Simon Ser
2019-05-10 11:38   ` Arkadiusz Hiler
2019-04-26 16:21 ` [igt-dev] [PATCH i-g-t 6/7] tests/kms_chamelium: don't abort audio test on first fail Simon Ser
2019-04-26 16:21 ` [igt-dev] [PATCH i-g-t 7/7] HAX: add dp-audio test to fast-feedback Simon Ser
2019-04-26 17:13 ` [igt-dev] ✗ Fi.CI.BAT: failure for tests/kms_chamelium: add hdmi-audio test Patchwork
2019-05-10 11:56   ` Arkadiusz Hiler

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20190426162110.1768-4-simon.ser@intel.com \
    --to=simon.ser@intel.com \
    --cc=igt-dev@lists.freedesktop.org \
    --cc=martin.peres@intel.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox