diff mbox

[i-g-t,1/1] chamelium: Add work in progress test for HDMI audio integrity testing

Message ID 20170831130404.21928-2-paul.kocialkowski@linux.intel.com (mailing list archive)
State New, archived
Headers show

Commit Message

Paul Kocialkowki Aug. 31, 2017, 1:04 p.m. UTC
This adds preliminary support for testing HDMI audio integrity with the
Chamelium. It aims to use the ALSA and audio IGT libraries to generate a
signal with a list of given frequencies, output it through HDMI and check
that the correct frequencies (and only those) are detected.

The test is currently work in progress and is not working. It is sent
only for reference and should not be merged.

Signed-off-by: Paul Kocialkowski <paul.kocialkowski@linux.intel.com>
---
 configure.ac        |  9 +++--
 lib/igt_chamelium.c | 18 ++++++++--
 lib/igt_chamelium.h |  6 +++-
 tests/Makefile.am   |  4 +--
 tests/chamelium.c   | 95 +++++++++++++++++++++++++++++++++++++++++++++++++++--
 5 files changed, 121 insertions(+), 11 deletions(-)
diff mbox

Patch

diff --git a/configure.ac b/configure.ac
index 41ec4d26..dd5d68b6 100644
--- a/configure.ac
+++ b/configure.ac
@@ -184,6 +184,9 @@  fi
 PKG_CHECK_MODULES(GSL, [gsl], [gsl=yes], [gsl=no])
 AM_CONDITIONAL(HAVE_GSL, [test "x$gsl" = xyes])
 
+PKG_CHECK_MODULES(ALSA, [alsa], [alsa=yes], [alsa=no])
+AM_CONDITIONAL(HAVE_ALSA, [test "x$alsa" = xyes])
+
 # for chamelium
 AC_ARG_ENABLE(chamelium, AS_HELP_STRING([--enable-chamelium],
 	      [Enable building of chamelium libraries and tests (default: no)]),
@@ -215,13 +218,13 @@  if test "x$enable_chamelium" = xyes; then
 	if test x"$gsl" != xyes; then
 		AC_MSG_ERROR([Failed to find gsl, required by chamelium.])
 	fi
+	if test x"$alsa" != xyes; then
+		AC_MSG_ERROR([Failed to find ALSA, required by chamelium.])
+	fi
 
 	AC_DEFINE(HAVE_CHAMELIUM, 1, [Enable Chamelium support])
 fi
 
-PKG_CHECK_MODULES(ALSA, [alsa], [alsa=yes], [alsa=no])
-AM_CONDITIONAL(HAVE_ALSA, [test "x$alsa" = xyes])
-
 # for audio
 AC_ARG_ENABLE(audio, AS_HELP_STRING([--enable-audio],
 	      [Enable building of audio tests (default: no)]),
diff --git a/lib/igt_chamelium.c b/lib/igt_chamelium.c
index dcd8855f..b4d98cd6 100644
--- a/lib/igt_chamelium.c
+++ b/lib/igt_chamelium.c
@@ -484,14 +484,14 @@  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 *edid, int size)
 {
 	xmlrpc_value *res;
 	struct chamelium_edid *allocated_edid;
 	int edid_id;
 
 	res = chamelium_rpc(chamelium, NULL, "CreateEdid", "(6)",
-			    edid, EDID_LENGTH);
+			    edid, size);
 
 	xmlrpc_read_int(&chamelium->env, res, &edid_id);
 	xmlrpc_DECREF(res);
@@ -1376,6 +1376,20 @@  igt_crc_t *chamelium_calculate_fb_crc_async_finish(struct chamelium_fb_crc_async
 	return ret;
 }
 
+void chamelium_start_capturing_audio(struct chamelium *chamelium,
+				     struct chamelium_port *port)
+{
+	xmlrpc_DECREF(chamelium_rpc(chamelium, port, "StartCapturingAudio",
+				    "(ib)", port->id, true));
+}
+
+void chamelium_stop_capturing_audio(struct chamelium *chamelium,
+				    struct chamelium_port *port)
+{
+	xmlrpc_DECREF(chamelium_rpc(chamelium, port, "StopCapturingAudio",
+				    "(i)", port->id));
+}
+
 static unsigned int chamelium_get_port_type(struct chamelium *chamelium,
 					    struct chamelium_port *port)
 {
diff --git a/lib/igt_chamelium.h b/lib/igt_chamelium.h
index 2a0fa234..c71a8620 100644
--- a/lib/igt_chamelium.h
+++ b/lib/igt_chamelium.h
@@ -65,7 +65,7 @@  void chamelium_fire_hpd_pulses(struct chamelium *chamelium,
 void chamelium_schedule_hpd_toggle(struct chamelium *chamelium,
 				   struct chamelium_port *port, int delay_ms,
 				   bool rising_edge);
-int chamelium_new_edid(struct chamelium *chamelium, const unsigned char *edid);
+int chamelium_new_edid(struct chamelium *chamelium, const unsigned char *edid, int size);
 void chamelium_port_set_edid(struct chamelium *chamelium,
 			     struct chamelium_port *port, int edid_id);
 bool chamelium_port_get_ddc_state(struct chamelium *chamelium,
@@ -115,5 +115,9 @@  void chamelium_assert_analog_frame_match_or_dump(struct chamelium *chamelium,
 void chamelium_crop_analog_frame(struct chamelium_frame_dump *dump, int width,
 				 int height);
 void chamelium_destroy_frame_dump(struct chamelium_frame_dump *dump);
+void chamelium_start_capturing_audio(struct chamelium *chamelium,
+				     struct chamelium_port *port);
+void chamelium_stop_capturing_audio(struct chamelium *chamelium,
+				    struct chamelium_port *port);
 
 #endif /* IGT_CHAMELIUM_H */
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 726e2b27..82ca5159 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -138,8 +138,8 @@  vc4_wait_bo_LDADD = $(LDADD) $(DRM_VC4_LIBS)
 vc4_wait_seqno_CFLAGS = $(AM_CFLAGS) $(DRM_VC4_CFLAGS)
 vc4_wait_seqno_LDADD = $(LDADD) $(DRM_VC4_LIBS)
 
-chamelium_CFLAGS = $(AM_CFLAGS) $(XMLRPC_CFLAGS) $(LIBUDEV_CFLAGS)
-chamelium_LDADD = $(LDADD) $(XMLRPC_LIBS) $(LIBUDEV_LIBS)
+chamelium_CFLAGS = $(AM_CFLAGS) $(XMLRPC_CFLAGS) $(LIBUDEV_CFLAGS) $(ALSA_CFLAGS)
+chamelium_LDADD = $(LDADD) $(XMLRPC_LIBS) $(LIBUDEV_LIBS) $(ALSA_LIBS)
 
 audio_CFLAGS = $(AM_CFLAGS) $(ALSA_CFLAGS)
 audio_LDADD = $(LDADD) $(ALSA_LIBS)
diff --git a/tests/chamelium.c b/tests/chamelium.c
index e3d81357..aa33e3c7 100644
--- a/tests/chamelium.c
+++ b/tests/chamelium.c
@@ -39,6 +39,7 @@  typedef struct {
 
 	int edid_id;
 	int alt_edid_id;
+	int audio_edid_id;
 } data_t;
 
 #define HOTPLUG_TIMEOUT 20 /* seconds */
@@ -728,6 +729,82 @@  test_hpd_storm_disable(data_t *data, struct chamelium_port *port, int width)
 	igt_hpd_storm_reset(data->drm_fd);
 }
 
+static int test_frequencies[] = {
+	300,
+	600,
+	1200,
+	80000,
+	10000,
+};
+
+static int test_frequencies_count = sizeof(test_frequencies) / sizeof(int);
+
+static int
+output_callback(void *data, short *buffer, int frames)
+{
+	struct audio_signal *signal = (struct audio_signal *) data;
+
+	audio_signal_fill(signal, buffer, frames);
+
+	return 0;
+}
+
+static void
+test_audio_integrity(data_t *data, struct chamelium_port *port, int edid_id)
+{
+	struct audio_signal *signal;
+	struct alsa *alsa;
+	int ret;
+	int j;
+
+	reset_state(data, port);
+
+	chamelium_port_set_edid(data->chamelium, port, edid_id);
+	chamelium_plug(data->chamelium, port);
+	wait_for_connector(data, port, DRM_MODE_CONNECTED);
+
+	alsa = alsa_init();
+	igt_assert(alsa);
+
+	ret = alsa_open_output(alsa, "HDMI");
+	igt_assert(ret >= 0);
+
+	alsa_configure_output(alsa, 2, 44100);
+
+	signal = audio_signal_init(2, 44100);
+	igt_assert(signal);
+
+	for (j = 0; j < test_frequencies_count; j++)
+		audio_signal_add_frequency(signal,
+					   test_frequencies[j]);
+
+	audio_signal_synthesize(signal);
+
+	alsa_register_output_callback(alsa, output_callback,
+				      signal, 1024);
+
+	igt_debug("starting audio capture\n");
+	chamelium_start_capturing_audio(data->chamelium, port);
+
+	ret = alsa_run(alsa, 2000);
+	igt_assert(ret > 0);
+
+	audio_signal_clean(signal);
+	free(signal);
+
+	igt_debug("stopping audio capture\n");
+	chamelium_stop_capturing_audio(data->chamelium, port);
+
+	// TODO: Retrieve audio from Chamelium.
+
+	alsa_close_output(alsa);
+
+	/* TODO: Call audio_signal_detect with each 2048 captured frames
+	 * and assert that at least 3 in a row give a positive result.
+	 */
+
+}
+
 #define for_each_port(p, port)            \
 	for (p = 0, port = data.ports[p]; \
 	     p < data.port_count;         \
@@ -744,7 +821,9 @@  static data_t data;
 igt_main
 {
 	struct chamelium_port *port;
-	int edid_id, alt_edid_id, p;
+	int edid_id, alt_edid_id, audio_edid_id, p;
+	unsigned char *edid;
+	size_t length;
 
 	igt_fixture {
 		igt_skip_on_simulation();
@@ -757,11 +836,17 @@  igt_main
 						 &data.port_count);
 
 		edid_id = chamelium_new_edid(data.chamelium,
-					     igt_kms_get_base_edid());
+					     igt_kms_get_base_edid(), EDID_LENGTH);
 		alt_edid_id = chamelium_new_edid(data.chamelium,
-						 igt_kms_get_alt_edid());
+						 igt_kms_get_alt_edid(), EDID_LENGTH);
+
+		kmstest_edid_add_audio(igt_kms_get_base_edid(), EDID_LENGTH,
+				       &edid, &length);
+		audio_edid_id = chamelium_new_edid(data.chamelium, edid, length);
+
 		data.edid_id = edid_id;
 		data.alt_edid_id = alt_edid_id;
+		data.audio_edid_id = audio_edid_id;
 
 		/* So fbcon doesn't try to reprobe things itself */
 		kmstest_set_vt_graphics_mode();
@@ -893,6 +978,9 @@  igt_main
 
 		connector_subtest("hdmi-frame-dump", HDMIA)
 			test_display_frame_dump(&data, port);
+
+		connector_subtest("hdmi-audio-integrity", HDMIA)
+			test_audio_integrity(&data, port, audio_edid_id);
 	}
 
 	igt_subtest_group {
@@ -944,6 +1032,7 @@  igt_main
 	}
 
 	igt_fixture {
+		free(edid);
 		close(data.drm_fd);
 	}
 }