summaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rw-r--r--tests/audio.c193
-rw-r--r--tests/kms_chamelium.c276
-rw-r--r--tests/meson.build9
3 files changed, 271 insertions, 207 deletions
diff --git a/tests/audio.c b/tests/audio.c
deleted file mode 100644
index 560876a3..00000000
--- a/tests/audio.c
+++ /dev/null
@@ -1,193 +0,0 @@
-/*
- * Copyright © 2017 Intel Corporation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- *
- * Authors:
- * Paul Kocialkowski <paul.kocialkowski@linux.intel.com>
- */
-
-#include "config.h"
-#include "igt.h"
-
-#define PLAYBACK_CHANNELS 2
-#define PLAYBACK_FRAMES 1024
-
-#define CAPTURE_SAMPLE_RATE 48000
-#define CAPTURE_CHANNELS 2
-#define CAPTURE_DEVICE_NAME "default"
-#define CAPTURE_FRAMES 2048
-
-#define RUN_TIMEOUT 2000
-
-struct test_data {
- struct alsa *alsa;
- struct audio_signal *signal;
-
- int streak;
-};
-
-static int sampling_rates[] = {
- 32000,
- 44100,
- 48000,
- 88200,
- 96000,
- 176400,
- 192000,
-};
-
-static int sampling_rates_count = sizeof(sampling_rates) / sizeof(int);
-
-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 test_data *test_data = (struct test_data *) data;
-
- audio_signal_fill(test_data->signal, buffer, frames);
-
- return 0;
-}
-
-static int input_callback(void *data, short *buffer, int frames)
-{
- struct test_data *test_data = (struct test_data *) data;
- bool detect;
-
- detect = audio_signal_detect(test_data->signal, CAPTURE_CHANNELS,
- CAPTURE_SAMPLE_RATE, buffer, frames);
- if (detect)
- test_data->streak++;
- else
- test_data->streak = 0;
-
- /* A streak of 3 gives confidence that the signal is good. */
- if (test_data->streak == 3)
- return 1;
-
- return 0;
-}
-
-static void test_integrity(const char *device_name)
-{
- struct test_data data;
- int sampling_rate;
- bool run = false;
- bool test;
- int i, j;
- int ret;
-
- data.alsa = alsa_init();
- igt_assert(data.alsa);
-
- ret = alsa_open_input(data.alsa, CAPTURE_DEVICE_NAME);
- igt_assert(ret >= 0);
-
- alsa_configure_input(data.alsa, CAPTURE_CHANNELS,
- CAPTURE_SAMPLE_RATE);
-
- alsa_register_input_callback(data.alsa, input_callback, &data,
- CAPTURE_FRAMES);
-
- for (i = 0; i < sampling_rates_count; i++) {
- ret = alsa_open_output(data.alsa, device_name);
- igt_assert(ret >= 0);
-
- sampling_rate = sampling_rates[i];
-
- test = alsa_test_output_configuration(data.alsa,
- PLAYBACK_CHANNELS,
- sampling_rate);
- if (!test) {
- alsa_close_output(data.alsa);
- continue;
- }
-
- igt_debug("Testing with sampling rate %d\n", sampling_rate);
-
- alsa_configure_output(data.alsa, PLAYBACK_CHANNELS,
- sampling_rate);
-
- data.signal = audio_signal_init(PLAYBACK_CHANNELS,
- sampling_rate);
- igt_assert(data.signal);
-
- for (j = 0; j < test_frequencies_count; j++)
- audio_signal_add_frequency(data.signal,
- test_frequencies[j]);
-
- audio_signal_synthesize(data.signal);
-
- alsa_register_output_callback(data.alsa, output_callback,
- &data, PLAYBACK_FRAMES);
-
- data.streak = 0;
-
- ret = alsa_run(data.alsa, RUN_TIMEOUT);
- igt_assert(ret > 0);
-
- audio_signal_clean(data.signal);
- free(data.signal);
-
- alsa_close_output(data.alsa);
-
- run = true;
- }
-
- /* Make sure we tested at least one frequency */
- igt_assert(run);
-
- alsa_close_input(data.alsa);
- free(data.alsa);
-}
-
-static void test_suspend_resume_integrity(const char *device_name,
- enum igt_suspend_state state,
- enum igt_suspend_test test)
-{
- test_integrity(device_name);
-
- igt_system_suspend_autoresume(state, test);
-
- test_integrity(device_name);
-}
-
-igt_main
-{
- igt_subtest("hdmi-integrity")
- test_integrity("HDMI");
-
- igt_subtest("hdmi-integrity-after-suspend")
- test_suspend_resume_integrity("HDMI", SUSPEND_STATE_MEM,
- SUSPEND_TEST_NONE);
-
- igt_subtest("hdmi-integrity-after-hibernate")
- test_suspend_resume_integrity("HDMI", SUSPEND_STATE_DISK,
- SUSPEND_TEST_DEVICES);
-}
diff --git a/tests/kms_chamelium.c b/tests/kms_chamelium.c
index 2dc1049d..a712250a 100644
--- a/tests/kms_chamelium.c
+++ b/tests/kms_chamelium.c
@@ -413,7 +413,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)
+ struct chamelium_port *port, bool set_edid)
{
igt_display_t *display = &data->display;
igt_output_t *output;
@@ -428,7 +428,8 @@ prepare_output(data_t *data,
/* The chamelium's default EDID has a lot of resolutions, way more then
* we need to test
*/
- chamelium_port_set_edid(data->chamelium, port, data->edid_id);
+ if (set_edid)
+ chamelium_port_set_edid(data->chamelium, port, data->edid_id);
chamelium_plug(data->chamelium, port);
wait_for_connector(data, port, DRM_MODE_CONNECTED);
@@ -613,7 +614,7 @@ static void test_display_one_mode(data_t *data, struct chamelium_port *port,
reset_state(data, port);
- output = prepare_output(data, port);
+ output = prepare_output(data, port, true);
connector = chamelium_port_get_connector(data->chamelium, port, false);
primary = igt_output_get_plane_type(output, DRM_PLANE_TYPE_PRIMARY);
igt_assert(primary);
@@ -644,7 +645,7 @@ static void test_display_all_modes(data_t *data, struct chamelium_port *port,
reset_state(data, port);
- output = prepare_output(data, port);
+ output = prepare_output(data, port, true);
connector = chamelium_port_get_connector(data->chamelium, port, false);
primary = igt_output_get_plane_type(output, DRM_PLANE_TYPE_PRIMARY);
igt_assert(primary);
@@ -679,7 +680,7 @@ test_display_frame_dump(data_t *data, struct chamelium_port *port)
reset_state(data, port);
- output = prepare_output(data, port);
+ output = prepare_output(data, port, true);
connector = chamelium_port_get_connector(data->chamelium, port, false);
primary = igt_output_get_plane_type(output, DRM_PLANE_TYPE_PRIMARY);
igt_assert(primary);
@@ -710,6 +711,266 @@ test_display_frame_dump(data_t *data, struct chamelium_port *port)
drmModeFreeConnector(connector);
}
+
+/* Playback parameters control the audio signal we synthesize and send */
+#define PLAYBACK_CHANNELS 2
+#define PLAYBACK_SAMPLES 1024
+
+/* Capture paremeters control the audio signal we receive */
+#define CAPTURE_SAMPLES 2048
+
+#define AUDIO_DURATION 2000 /* ms */
+/* A streak of 3 gives confidence that the signal is good. */
+#define MIN_STREAK 3
+
+/* TODO: Chamelium only supports 48KHz for now */
+static int sampling_rates[] = {
+/* 32000, */
+/* 44100, */
+ 48000,
+/* 88200, */
+/* 96000, */
+/* 176400, */
+/* 192000, */
+};
+
+static int sampling_rates_count = sizeof(sampling_rates) / sizeof(int);
+
+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 bool
+do_test_display_audio(data_t *data, struct chamelium_port *port,
+ struct alsa *alsa, int playback_channels,
+ int playback_rate)
+{
+ int ret, capture_rate, capture_channels, msec;
+ struct chamelium_audio_file *audio_file;
+ struct chamelium_stream *stream;
+ enum chamelium_stream_realtime_mode stream_mode;
+ struct audio_signal *signal;
+ int32_t *recv, *buf;
+ double *channel;
+ size_t i, streak, page_count;
+ size_t recv_len, buf_len, buf_cap, buf_size, channel_len;
+ bool ok;
+ char dump_suffix[64];
+ char *dump_path = NULL;
+ int dump_fd = -1;
+
+ if (!alsa_test_output_configuration(alsa, playback_channels,
+ playback_rate))
+ return false;
+
+ igt_debug("Testing with playback sampling rate %d\n", playback_rate);
+ alsa_configure_output(alsa, playback_channels, playback_rate);
+
+ chamelium_start_capturing_audio(data->chamelium, port, false);
+
+ stream = chamelium_stream_init();
+ igt_assert(stream);
+
+ stream_mode = CHAMELIUM_STREAM_REALTIME_STOP_WHEN_OVERFLOW;
+ ok = chamelium_stream_dump_realtime_audio(stream, stream_mode);
+ igt_assert(ok);
+
+ chamelium_stream_audio_format(stream, &capture_rate, &capture_channels);
+
+ if (igt_frame_dump_is_enabled()) {
+ snprintf(dump_suffix, sizeof(dump_suffix), "capture-%dch-%d",
+ playback_channels, playback_rate);
+
+ dump_fd = audio_create_wav_file_s32_le(dump_suffix,
+ capture_rate,
+ capture_channels,
+ &dump_path);
+ igt_assert(dump_fd >= 0);
+ }
+
+ signal = audio_signal_init(playback_channels, playback_rate);
+ igt_assert(signal);
+
+ for (i = 0; i < test_frequencies_count; i++)
+ audio_signal_add_frequency(signal, test_frequencies[i]);
+ audio_signal_synthesize(signal);
+
+ alsa_register_output_callback(alsa, output_callback, signal,
+ PLAYBACK_SAMPLES);
+
+ /* TODO: detect signal in real-time */
+ ret = alsa_run(alsa, AUDIO_DURATION);
+ igt_assert(ret == 0);
+
+ alsa_close_output(alsa);
+
+ /* Needs to be a multiple of 128, because that's the number of samples
+ * we get per channel each time we receive an audio page from the
+ * Chamelium device. */
+ channel_len = CAPTURE_SAMPLES;
+ channel = malloc(sizeof(double) * channel_len);
+
+ buf_cap = capture_channels * channel_len;
+ buf = malloc(sizeof(int32_t) * buf_cap);
+ buf_len = 0;
+
+ recv = NULL;
+ recv_len = 0;
+
+ streak = 0;
+ msec = 0;
+ i = 0;
+ while (streak < MIN_STREAK && msec < AUDIO_DURATION) {
+ ok = chamelium_stream_receive_realtime_audio(stream,
+ &page_count,
+ &recv, &recv_len);
+ igt_assert(ok);
+
+ memcpy(&buf[buf_len], recv, recv_len * sizeof(int32_t));
+ buf_len += recv_len;
+
+ if (buf_len < buf_cap)
+ continue;
+ igt_assert(buf_len == buf_cap);
+
+ if (dump_fd >= 0) {
+ buf_size = buf_len * sizeof(int32_t);
+ igt_assert(write(dump_fd, buf, buf_size) == buf_size);
+ }
+
+ /* TODO: check other channels too, not just the first one */
+ audio_extract_channel_s32_le(channel, channel_len, buf, buf_len,
+ capture_channels, 0);
+
+ msec = i * channel_len / (double) capture_rate * 1000;
+ igt_debug("Detecting audio signal, t=%d msec\n", msec);
+
+ if (audio_signal_detect(signal, capture_rate, channel,
+ channel_len))
+ streak++;
+ else
+ streak = 0;
+
+ buf_len = 0;
+ i++;
+ }
+
+ if (dump_fd >= 0) {
+ close(dump_fd);
+ if (streak == MIN_STREAK) {
+ /* Test succeeded, no need to keep the captured data */
+ unlink(dump_path);
+ } else
+ igt_debug("Saved captured audio data to %s\n", dump_path);
+ free(dump_path);
+ }
+
+ free(recv);
+ free(buf);
+ free(channel);
+
+ ok = chamelium_stream_stop_realtime_audio(stream);
+ igt_assert(ok);
+
+ audio_file = chamelium_stop_capturing_audio(data->chamelium,
+ port);
+ if (audio_file) {
+ igt_debug("Audio file saved on the Chamelium in %s\n",
+ audio_file->path);
+ chamelium_destroy_audio_file(audio_file);
+ }
+
+ audio_signal_clean(signal);
+ free(signal);
+
+ chamelium_stream_deinit(stream);
+
+ igt_assert(streak == MIN_STREAK);
+ return true;
+}
+
+static void
+test_display_audio(data_t *data, struct chamelium_port *port,
+ const char *audio_device)
+{
+ bool run = false;
+ struct alsa *alsa;
+ int ret;
+ igt_output_t *output;
+ igt_plane_t *primary;
+ struct igt_fb fb;
+ drmModeModeInfo *mode;
+ drmModeConnector *connector;
+ int fb_id, i;
+
+ igt_require(alsa_has_exclusive_access());
+
+ alsa = alsa_init();
+ igt_assert(alsa);
+
+ 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);
+ connector = chamelium_port_get_connector(data->chamelium, port, false);
+ primary = igt_output_get_plane_type(output, DRM_PLANE_TYPE_PRIMARY);
+ igt_assert(primary);
+
+ /* Enable the output because the receiver won't try to receive audio if
+ * it doesn't receive video. */
+ igt_assert(connector->count_modes > 0);
+ mode = &connector->modes[0];
+
+ fb_id = igt_create_color_pattern_fb(data->drm_fd,
+ mode->hdisplay, mode->vdisplay,
+ DRM_FORMAT_XRGB8888,
+ LOCAL_DRM_FORMAT_MOD_NONE,
+ 0, 0, 0, &fb);
+ igt_assert(fb_id > 0);
+
+ enable_output(data, port, output, mode, &fb);
+
+ for (i = 0; i < 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]);
+
+ alsa_close_output(alsa);
+ }
+
+ /* Make sure we tested at least one frequency. */
+ igt_assert(run);
+
+ igt_remove_fb(data->drm_fd, &fb);
+
+ drmModeFreeConnector(connector);
+
+ free(alsa);
+}
+
+
static void select_tiled_modifier(igt_plane_t *plane, uint32_t width,
uint32_t height, uint32_t format,
uint64_t *modifier)
@@ -1037,7 +1298,7 @@ static void test_display_planes_random(data_t *data,
reset_state(data, port);
/* Find the connector and pipe. */
- output = prepare_output(data, port);
+ output = prepare_output(data, port, true);
mode = igt_output_get_mode(output);
@@ -1308,6 +1569,9 @@ igt_main
connector_subtest("dp-frame-dump", DisplayPort)
test_display_frame_dump(&data, port);
+
+ connector_subtest("dp-audio", DisplayPort)
+ test_display_audio(&data, port, "HDMI");
}
igt_subtest_group {
diff --git a/tests/meson.build b/tests/meson.build
index e3c8b07f..711979b4 100644
--- a/tests/meson.build
+++ b/tests/meson.build
@@ -239,20 +239,13 @@ if libdrm_nouveau.found()
test_deps += libdrm_nouveau
endif
-if _build_chamelium and chamelium.found()
+if chamelium_found
test_progs += [
'kms_chamelium',
]
test_deps += chamelium
endif
-if _build_audio and alsa.found() and gsl.found()
- test_progs += [
- 'audio',
- ]
- test_deps += alsa
-endif
-
test_executables = []
test_list = []