[igt-dev] [PATCH] [NEW]kms_chamelium: Add new EDID stress resolution test
Petri Latvala
petri.latvala at intel.com
Mon Oct 31 11:13:07 UTC 2022
On Fri, Oct 28, 2022 at 12:42:55PM -0400, Mark Yacoub wrote:
> [Why]
> 2 things that happen concurrently that we would like to test:
> 1. Test multiple plug/unplug of different monitors (as in different
> EDIDs) to the DUT in a short time span.
> 2. Test that the different EDIDs are understood well by the DUT through
> verifying the resolution after each plug and enable output.
>
> [How]
> 1. Get EDID from list of EDIDs
> 2. Set the EDID
> 3. Plug and enable display
> 4. Check the resolution
> 5. Unplug and repeat.
>
> TODO:
> 1. Add more EDIDs
> 2. Do the same for HDMI
>
> Test Based on: [ChromeOS AutoTest display_EdidStress](https://chromium.googlesource.com/chromiumos/third_party/autotest/+/HEAD/server/site_tests/display_EdidStress/display_EdidStress.py)
>
> Tested on: TGL with Cv3
>
> Signed-off-by: Mark Yacoub <markyacoub at chromium.org>
Recap of offline discussions:
Main concerns of this kind of a test is the amount of runtime and disk
space used. With the log level we use in i915 CI, hotplugs can
generate a log of dmesg. Runtime seems to be alright, reported to be
around 8s per EDID.
Gitlab-pipeline reported some build warns that you have to fix. With
that done, this is
Acked-by: Petri Latvala <petri.latvala at intel.com>
> ---
> lib/igt_chamelium.c | 10 +--
> lib/igt_chamelium.h | 22 +++++-
> lib/meson.build | 4 +-
> lib/monitor_edids/dp_edids.h | 56 +++++++++++++++
> lib/monitor_edids/monitor_edids_helper.c | 92 ++++++++++++++++++++++++
> lib/monitor_edids/monitor_edids_helper.h | 33 +++++++++
> tests/chamelium/kms_chamelium.c | 75 +++++++++++++++++++
> 7 files changed, 278 insertions(+), 14 deletions(-)
> create mode 100644 lib/monitor_edids/dp_edids.h
> create mode 100644 lib/monitor_edids/monitor_edids_helper.c
> create mode 100644 lib/monitor_edids/monitor_edids_helper.h
>
> diff --git a/lib/igt_chamelium.c b/lib/igt_chamelium.c
> index d998a1f1..db3ca0d7 100644
> --- a/lib/igt_chamelium.c
> +++ b/lib/igt_chamelium.c
> @@ -91,14 +91,6 @@
> */
> #define CHAMELIUM_HOTPLUG_DETECTION_DELAY 10
>
> -struct chamelium_edid {
> - struct chamelium *chamelium;
> - struct edid *base;
> - struct edid *raw[CHAMELIUM_MAX_PORTS];
> - int ids[CHAMELIUM_MAX_PORTS];
> - struct igt_list_head link;
> -};
> -
> struct chamelium_port {
> unsigned int type;
> int id;
> @@ -688,7 +680,7 @@ static xmlrpc_value *chamelium_rpc(struct chamelium *chamelium,
> va_end(va_args);
> }
> igt_assert_f(!chamelium->env.fault_occurred,
> - "Chamelium RPC call failed: %s\n",
> + "Chamelium RPC call[%s] failed: %s\n", method_name,
> chamelium->env.fault_string);
>
> return res;
> diff --git a/lib/igt_chamelium.h b/lib/igt_chamelium.h
> index e1ee2b59..6da4ef66 100644
> --- a/lib/igt_chamelium.h
> +++ b/lib/igt_chamelium.h
> @@ -33,6 +33,7 @@
>
> #include "igt_debugfs.h"
> #include "igt_kms.h"
> +#include "igt_list.h"
>
> struct igt_fb;
> struct edid;
> @@ -80,12 +81,11 @@ struct chamelium_infoframe {
> uint8_t *payload;
> };
>
> -struct chamelium_edid;
> -
> /**
> * CHAMELIUM_MAX_PORTS: the maximum number of ports supported by igt_chamelium.
> *
> - * For now, we have 1 VGA, 1 HDMI and 2 DisplayPort ports.
> + * On V2: 1 VGA, 1 HDMI and 2 DisplayPort ports.
> + * On V3: 2 HDMI and 2 DisplayPort ports.
> */
> #define CHAMELIUM_MAX_PORTS 4
>
> @@ -105,6 +105,22 @@ extern bool igt_chamelium_allow_fsm_handling;
>
> #define CHAMELIUM_HOTPLUG_TIMEOUT 20 /* seconds */
>
> +/**
> + * chamelium_edid:
> + * @chamelium: instance of the chamelium where the EDID will be applied
> + * @base: Unaltered EDID that would be used for all ports. Matches what you
> + * would get from a real monitor.
> + * @raw: EDID to be applied for each port.
> + * @ids: The ID received from Chamelium after it's created for specific ports.
> + */
> +struct chamelium_edid {
> + struct chamelium *chamelium;
> + struct edid *base;
> + struct edid *raw[CHAMELIUM_MAX_PORTS];
> + int ids[CHAMELIUM_MAX_PORTS];
> + struct igt_list_head link;
> +};
> +
> void chamelium_deinit_rpc_only(struct chamelium *chamelium);
> struct chamelium *chamelium_init_rpc_only(void);
> struct chamelium *chamelium_init(int drm_fd, igt_display_t *display);
> diff --git a/lib/meson.build b/lib/meson.build
> index 1fa6d6ee..0e0fc8a1 100644
> --- a/lib/meson.build
> +++ b/lib/meson.build
> @@ -164,8 +164,8 @@ endif
>
> if chamelium.found()
> lib_deps += chamelium
> - lib_sources += 'igt_chamelium.c'
> - lib_sources += 'igt_chamelium_stream.c'
> + lib_sources += [ 'igt_chamelium.c', 'igt_chamelium_stream.c' ]
> + lib_sources += 'monitor_edids/monitor_edids_helper.c'
> endif
>
> if get_option('srcdir') != ''
> diff --git a/lib/monitor_edids/dp_edids.h b/lib/monitor_edids/dp_edids.h
> new file mode 100644
> index 00000000..1217fedc
> --- /dev/null
> +++ b/lib/monitor_edids/dp_edids.h
> @@ -0,0 +1,56 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/*
> + * List of real DP EDIDs from popular monitors.
> + * The current list (at the time of writing this comment) is based on the top
> + * monitors used on ChromeOS.
> + *
> + * Copyright 2022 Google LLC.
> + *
> + * Authors: Mark Yacoub <markyacoub at chromium.org>
> + */
> +
> +#ifndef TESTS_CHAMELIUM_MONITOR_EDIDS_DP_EDIDS_H_
> +#define TESTS_CHAMELIUM_MONITOR_EDIDS_DP_EDIDS_H_
> +
> +#include "monitor_edids_helper.h"
> +
> +// TODO: Add more EDIDs.
> +struct monitor_edid DP_EDIDS[] = {
> + { .name = "4K_DELL_UP3216Q_DP",
> + .edid = "00ffffffffffff0010acf84050383230"
> + "051a0104a5431c783aca95a6554ea126"
> + "0f5054a54b808100b300714f8180d1c0"
> + "0101010101017e4800e0a0381f404040"
> + "3a00a11c2100001a000000ff00393143"
> + "5937333538303238500a000000fc0044"
> + "454c4c205532393137570a20000000fd"
> + "00314c1d5e13010a2020202020200117"
> + "02031df1501005040302071601061112"
> + "1513141f2023091f0783010000023a80"
> + "1871382d40582c2500a11c2100001e01"
> + "1d8018711c1620582c2500a11c210000"
> + "9e011d007251d01e206e285500a11c21"
> + "00001e8c0ad08a20e02d10103e9600a1"
> + "1c210000180000000000000000000000"
> + "000000000000000000000000000000dd" },
> +
> + { .name = "DEL_16543_DELL_P2314T_DP",
> + .edid = "00ffffffffffff0010ac9f404c4c3645"
> + "10180104a5331d783ae595a656529d27"
> + "105054a54b00714f8180a9c0d1c00101"
> + "010101010101023a801871382d40582c"
> + "4500fd1e1100001e000000ff00445746"
> + "325834344645364c4c0a000000fc0044"
> + "454c4c205032333134540a20000000fd"
> + "00384c1e5311010a20202020202001bb"
> + "02031cf14f9005040302071601061112"
> + "1513141f2309070783010000023a8018"
> + "71382d40582c4500fd1e1100001e011d"
> + "8018711c1620582c2500fd1e1100009e"
> + "011d007251d01e206e285500fd1e1100"
> + "001e8c0ad08a20e02d10103e9600fd1e"
> + "11000018000000000000000000000000"
> + "0000000000000000000000000000003f" }
> +};
> +
> +#endif /* TESTS_CHAMELIUM_MONITOR_EDIDS_DP_EDIDS_H_ */
> \ No newline at end of file
> diff --git a/lib/monitor_edids/monitor_edids_helper.c b/lib/monitor_edids/monitor_edids_helper.c
> new file mode 100644
> index 00000000..acea1431
> --- /dev/null
> +++ b/lib/monitor_edids/monitor_edids_helper.c
> @@ -0,0 +1,92 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * A helper library for parsing and making use of real EDID data from monitors
> + * and make them compatible with IGT and Chamelium.
> + *
> + * Copyright 2022 Google LLC.
> + *
> + * Authors: Mark Yacoub <markyacoub at chromium.org>
> + */
> +
> +#include "monitor_edids_helper.h"
> +
> +#include <stdlib.h>
> +#include <string.h>
> +#include <assert.h>
> +
> +#include "igt_core.h"
> +
> +static uint8_t convert_hex_char_to_byte(char c)
> +{
> + if (c >= '0' && c <= '9')
> + return c - '0';
> + if (c >= 'A' && c <= 'F')
> + return c - 'A' + 10;
> + if (c >= 'a' && c <= 'f')
> + return c - 'a' + 10;
> +
> + assert(0);
> + return 0;
> +}
> +
> +static uint8_t *get_edid_bytes_from_hex_str(const char *edid_str)
> +{
> + int i;
> +
> + int edid_size = strlen(edid_str) / 2; /* each asci is a nibble. */
> + uint8_t *edid = (uint8_t *)malloc(edid_size);
> +
> + for (i = 0; i < edid_size; i++) {
> + edid[i] = convert_hex_char_to_byte(edid_str[i * 2]) << 4 |
> + convert_hex_char_to_byte(edid_str[i * 2 + 1]);
> + }
> +
> + return edid;
> +}
> +
> +const char *monitor_edid_get_name(const struct monitor_edid *edid)
> +{
> + return edid->name;
> +}
> +
> +struct chamelium_edid *
> +get_chameleon_edid_from_monitor_edid(struct chamelium *chamelium,
> + const struct monitor_edid *edid)
> +{
> + int i;
> + struct chamelium_edid *chamelium_edid;
> +
> + uint8_t *base_edid = get_edid_bytes_from_hex_str(edid->edid);
> + assert(base_edid);
> +
> + /*Print the full formatted EDID on debug. */
> + for (i = 0; i < strlen(edid->edid) / 2; i++) {
> + igt_debug("%02x ", base_edid[i]);
> + if (i % 16 == 15)
> + igt_debug("\n");
> + }
> +
> + chamelium_edid = malloc(sizeof(struct chamelium_edid));
> + assert(chamelium_edid);
> +
> + chamelium_edid->base = base_edid;
> + chamelium_edid->chamelium = chamelium;
> + for (i = 0; i < CHAMELIUM_MAX_PORTS; i++) {
> + chamelium_edid->raw[i] = NULL;
> + chamelium_edid->ids[i] = 0;
> + }
> +
> + return chamelium_edid;
> +}
> +
> +void free_chamelium_edid_from_monitor_edid(struct chamelium_edid *edid)
> +{
> + int i;
> +
> + free(edid->base);
> + for (i = 0; i < CHAMELIUM_MAX_PORTS; i++)
> + free(edid->raw[i]);
> +
> + free(edid);
> + edid = NULL;
> +}
> diff --git a/lib/monitor_edids/monitor_edids_helper.h b/lib/monitor_edids/monitor_edids_helper.h
> new file mode 100644
> index 00000000..46f85629
> --- /dev/null
> +++ b/lib/monitor_edids/monitor_edids_helper.h
> @@ -0,0 +1,33 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/*
> + * A helper library for parsing and making use of real EDID data from monitors
> + * and make them compatible with IGT and Chamelium.
> + *
> + * Copyright 2022 Google LLC.
> + *
> + * Authors: Mark Yacoub <markyacoub at chromium.org>
> + */
> +
> +#ifndef TESTS_CHAMELIUM_MONITOR_EDIDS_MONITOR_EDIDS_HELPER_H_
> +#define TESTS_CHAMELIUM_MONITOR_EDIDS_MONITOR_EDIDS_HELPER_H_
> +
> +#include <stdint.h>
> +
> +#include "igt_chamelium.h"
> +
> +/* Max Length can be increased as needed, when new EDIDs are added. */
> +#define EDID_NAME_MAX_LEN 25
> +#define EDID_HEX_STR_MAX_LEN 512
> +
> +struct monitor_edid {
> + char name[EDID_NAME_MAX_LEN];
> + char edid[EDID_HEX_STR_MAX_LEN + 1];
> +};
> +
> +const char *monitor_edid_get_name(const struct monitor_edid *edid);
> +struct chamelium_edid *
> +get_chameleon_edid_from_monitor_edid(struct chamelium *chamelium,
> + const struct monitor_edid *edid);
> +void free_chamelium_edid_from_monitor_edid(struct chamelium_edid *edid);
> +
> +#endif /* TESTS_CHAMELIUM_MONITOR_EDIDS_MONITOR_EDIDS_HELPER_H_ */
> \ No newline at end of file
> diff --git a/tests/chamelium/kms_chamelium.c b/tests/chamelium/kms_chamelium.c
> index 99cc23a1..6e77ba3c 100644
> --- a/tests/chamelium/kms_chamelium.c
> +++ b/tests/chamelium/kms_chamelium.c
> @@ -30,11 +30,16 @@
> #include "igt_edid.h"
> #include "igt_eld.h"
> #include "igt_infoframe.h"
> +#include "monitor_edids/dp_edids.h"
> +#include "monitor_edids/monitor_edids_helper.h"
>
> #include <fcntl.h>
> #include <pthread.h>
> #include <string.h>
> #include <stdatomic.h>
> +// #include <stdio.h>
> +
> +// struct chamelium_edid;
>
> enum test_modeset_mode {
> TEST_MODESET_ON,
> @@ -2541,6 +2546,71 @@ test_hpd_storm_disable(data_t *data, struct chamelium_port *port, int width)
> igt_hpd_storm_reset(data->drm_fd);
> }
>
> +static const char igt_edid_stress_resolution_desc[] =
> + "Stress test the DUT by testing multiple EDIDs, one right after the other,"
> + "and ensure their validity by check the real screen resolution vs the"
> + "advertised mode resultion.";
> +static void edid_stress_resolution(data_t *data, struct chamelium_port *port,
> + struct monitor_edid edids_list[],
> + size_t edids_list_len)
> +{
> + int i;
> + struct chamelium *chamelium = data->chamelium;
> + struct udev_monitor *mon = igt_watch_uevents();
> +
> + for (i = 0; i < edids_list_len; ++i) {
> + struct chamelium_edid *chamelium_edid;
> + drmModeModeInfo mode;
> + struct igt_fb fb = { 0 };
> + igt_output_t *output;
> + enum pipe pipe;
> + bool is_video_stable;
> + int screen_res_w, screen_res_h;
> +
> + struct monitor_edid *monitor_edid = &edids_list[i];
> + igt_info("Testing out the EDID for %s\n",
> + monitor_edid_get_name(monitor_edid));
> +
> + /* Getting and Setting the EDID on Chamelium. */
> + chamelium_edid = get_chameleon_edid_from_monitor_edid(
> + chamelium, monitor_edid);
> + chamelium_port_set_edid(data->chamelium, port, chamelium_edid);
> + free_chamelium_edid_from_monitor_edid(chamelium_edid);
> +
> + igt_flush_uevents(mon);
> + chamelium_plug(chamelium, port);
> + wait_for_connector_after_hotplug(data, mon, port,
> + DRM_MODE_CONNECTED);
> + igt_flush_uevents(mon);
> +
> + /* Setting an output on the screen to turn it on. */
> + mode = get_mode_for_port(chamelium, port);
> + create_fb_for_mode(data, &fb, &mode);
> + output = get_output_for_port(data, port);
> + pipe = get_pipe_for_output(&data->display, output);
> + igt_output_set_pipe(output, pipe);
> + enable_output(data, port, output, &mode, &fb);
> +
> + /* Capture the screen resolution and verify. */
> + is_video_stable = chamelium_port_wait_video_input_stable(
> + chamelium, port, 5);
> + igt_assert(is_video_stable);
> +
> + chamelium_port_get_resolution(chamelium, port, &screen_res_w,
> + &screen_res_h);
> + igt_assert(screen_res_w == fb.width);
> + igt_assert(screen_res_h == fb.height);
> +
> + // Clean up
> + igt_remove_fb(data->drm_fd, &fb);
> + igt_modeset_disable_all_outputs(&data->display);
> + chamelium_unplug(chamelium, port);
> + }
> +
> + chamelium_reset_state(&data->display, data->chamelium, port,
> + data->ports, data->port_count);
> +}
> +
> #define for_each_port(p, port) \
> for (p = 0, port = data.ports[p]; \
> p < data.port_count; \
> @@ -2632,6 +2702,11 @@ igt_main
> igt_custom_edid_type_read(&data, port, IGT_CUSTOM_EDID_ALT);
> }
>
> + igt_describe(igt_edid_stress_resolution_desc);
> + connector_subtest("dp-edid-stress-resolution", DisplayPort)
> + edid_stress_resolution(&data, port, DP_EDIDS,
> + ARRAY_SIZE(DP_EDIDS));
> +
> igt_describe(test_suspend_resume_hpd_desc);
> connector_subtest("dp-hpd-after-suspend", DisplayPort)
> test_suspend_resume_hpd(&data, port,
> --
> 2.38.1.273.g43a17bfeac-goog
>
More information about the igt-dev
mailing list