[igt-dev] [PATCH] [NEW] Chamelium: Add new EDID Resolution List test

Petri Latvala petri.latvala at intel.com
Thu Nov 10 08:34:20 UTC 2022


On Mon, Nov 07, 2022 at 12:18:45PM -0500, Mark Yacoub wrote:
> [Why]
> 1. Users can change resolutions of monitors on the fly.
> 2. Monitors can come with different shapes and form aka different modes.
> Test a change between different modes on the fly.
> 
> [How]
> 1. Created an EDID based on a random combination of screen size, Refresh
>    Rate and Aspect Ratio.
> 2. Set that EDID to Chamelium.
> 3. Iterate over every mode on the connector, assign it to the connector
>    and check that the screen resolution changes to this one.
> 
> Test Based on: [ChromeOS AutoTest
> display_ResolutionList](https://chromium.googlesource.com/chromiumos/third_party/autotest/+/HEAD/server/site_tests/display_ResolutionList/display_ResolutionList.py)
> 
> Tested on: TGL with Cv3
> 
> Signed-off-by: Mark Yacoub <markyacoub at chromium.org>
> ---
>  lib/igt_edid.c                  |  4 +-
>  lib/igt_edid.h                  |  2 +
>  lib/igt_kms.c                   | 31 +++++++++++++++
>  lib/igt_kms.h                   |  5 ++-
>  tests/chamelium/kms_chamelium.c | 68 +++++++++++++++++++++++++++++++++
>  5 files changed, 107 insertions(+), 3 deletions(-)
> 
> diff --git a/lib/igt_edid.c b/lib/igt_edid.c
> index bff13a0d..9c67e51b 100644
> --- a/lib/igt_edid.c
> +++ b/lib/igt_edid.c
> @@ -61,8 +61,8 @@ static const char monitor_range_padding[] = {
>  const uint8_t hdmi_ieee_oui[3] = {0x03, 0x0C, 0x00};
>  
>  /* vfreq is in Hz */
> -static void std_timing_set(struct std_timing *st, int hsize, int vfreq,
> -			   enum std_timing_aspect aspect)
> +void std_timing_set(struct std_timing *st, int hsize, int vfreq,
> +		    enum std_timing_aspect aspect)

Making this non-static comes with the cost of now having to write
documentation for it.


>  {
>  	assert(hsize >= 256 && hsize <= 2288);
>  	st->hsize = hsize / 8 - 31;
> diff --git a/lib/igt_edid.h b/lib/igt_edid.h
> index a9251d68..609f3cd4 100644
> --- a/lib/igt_edid.h
> +++ b/lib/igt_edid.h
> @@ -379,6 +379,8 @@ size_t edid_get_size(const struct edid *edid);
>  void edid_get_mfg(const struct edid *edid, char out[static 3]);
>  uint8_t edid_get_deep_color_from_vsdb(const struct edid *edid);
>  uint8_t edid_get_bit_depth_from_vid(const struct edid *edid);
> +void std_timing_set(struct std_timing *st, int hsize, int vfreq,
> +		    enum std_timing_aspect aspect); // rename
>  void detailed_timing_set_mode(struct detailed_timing *dt, drmModeModeInfo *mode,
>  			      int width_mm, int height_mm);
>  void detailed_timing_set_monitor_range_mode(struct detailed_timing *dt,
> diff --git a/lib/igt_kms.c b/lib/igt_kms.c
> index 921a623d..437977a7 100644
> --- a/lib/igt_kms.c
> +++ b/lib/igt_kms.c
> @@ -133,6 +133,35 @@ const struct edid *igt_kms_get_base_edid(void)
>  	return &edid;
>  }
>  
> +const struct edid *igt_kms_get_full_edid(void)
> +{
> +	static struct edid edid;
> +	drmModeModeInfo mode = {};
> +	mode.clock = 148500;
> +	mode.hdisplay = 2288;
> +	mode.hsync_start = 2008;
> +	mode.hsync_end = 2052;
> +	mode.htotal = 2200;
> +	mode.vdisplay = 1287;
> +	mode.vsync_start = 1084;
> +	mode.vsync_end = 1089;
> +	mode.vtotal = 1125;
> +	mode.vrefresh = 144;
> +	edid_init_with_mode(&edid, &mode);
> +
> +	std_timing_set(&edid.standard_timings[0], 256, 60, STD_TIMING_16_10);
> +	std_timing_set(&edid.standard_timings[1], 510, 69, STD_TIMING_4_3);
> +	std_timing_set(&edid.standard_timings[2], 764, 78, STD_TIMING_5_4);
> +	std_timing_set(&edid.standard_timings[3], 1018, 87, STD_TIMING_16_9);
> +	std_timing_set(&edid.standard_timings[4], 1526, 96, STD_TIMING_16_10);
> +	std_timing_set(&edid.standard_timings[5], 1780, 105, STD_TIMING_4_3);
> +	std_timing_set(&edid.standard_timings[6], 2034, 114, STD_TIMING_5_4);
> +	std_timing_set(&edid.standard_timings[7], 2288, 123, STD_TIMING_16_9);
> +
> +	edid_update_checksum(&edid);
> +	return &edid;
> +}
> +
>  const struct edid *igt_kms_get_base_tile_edid(void)
>  {
>  	static struct edid edid;
> @@ -548,6 +577,8 @@ const struct edid *igt_kms_get_custom_edid(enum igt_custom_edid_type edid)
>  	switch (edid) {
>  	case IGT_CUSTOM_EDID_BASE:
>  		return igt_kms_get_base_edid();
> +	case IGT_CUSTOM_EDID_FULL:
> +		return igt_kms_get_full_edid();
>  	case IGT_CUSTOM_EDID_ALT:
>  		return igt_kms_get_alt_edid();
>  	case IGT_CUSTOM_EDID_HDMI_AUDIO:
> diff --git a/lib/igt_kms.h b/lib/igt_kms.h
> index b09441d0..7a00d204 100644
> --- a/lib/igt_kms.h
> +++ b/lib/igt_kms.h
> @@ -82,6 +82,7 @@ enum port {
>   *
>   * Enum used for the helper function igt_custom_edid_type
>   * @IGT_CUSTOM_EDID_BASE: Returns base edid
> + * @IGT_CUSTOM_EDID_FULL: Returns edid with full list of standard timings.
>   * @IGT_CUSTOM_EDID_ALT: Returns alternate edid
>   * @IGT_CUSTOM_EDID_HDMI_AUDIO: Returns edid with HDMI audio block
>   * @IGT_CUSTOM_EDID_DP_AUDIO: Returns edid with DP audio block
> @@ -89,12 +90,13 @@ enum port {
>   */
>  enum igt_custom_edid_type {
>  	IGT_CUSTOM_EDID_BASE,
> +	IGT_CUSTOM_EDID_FULL,
>  	IGT_CUSTOM_EDID_ALT,
>  	IGT_CUSTOM_EDID_HDMI_AUDIO,
>  	IGT_CUSTOM_EDID_DP_AUDIO,
>  	IGT_CUSTOM_EDID_ASPECT_RATIO,
>  };
> -#define IGT_CUSTOM_EDID_COUNT 5
> +#define IGT_CUSTOM_EDID_COUNT 6
>  
>  /**
>   * kmstest_port_name:
> @@ -865,6 +867,7 @@ void igt_reset_connectors(void);
>  uint32_t kmstest_get_vbl_flag(int crtc_offset);
>  
>  const struct edid *igt_kms_get_base_edid(void);
> +const struct edid *igt_kms_get_full_edid(void);
>  const struct edid *igt_kms_get_base_tile_edid(void);
>  const struct edid *igt_kms_get_alt_edid(void);
>  const struct edid *igt_kms_get_hdmi_audio_edid(void);
> diff --git a/tests/chamelium/kms_chamelium.c b/tests/chamelium/kms_chamelium.c
> index 2bc97d5a..c8fbc45c 100644
> --- a/tests/chamelium/kms_chamelium.c
> +++ b/tests/chamelium/kms_chamelium.c
> @@ -2612,6 +2612,70 @@ static void edid_stress_resolution(data_t *data, struct chamelium_port *port,
>  			      data->ports, data->port_count);
>  }
>  
> +static const char igt_edid_resolution_list_desc[] =
> +	"Get an EDID with many modes of different configurations, set them on the screen and check the"
> +	"screen resolution matches the mode resolution.";
> +static void edid_resolution_list(data_t *data, struct chamelium_port *port)
> +{
> +	struct chamelium *chamelium = data->chamelium;
> +	struct udev_monitor *mon = igt_watch_uevents();
> +	drmModeConnector *init_connector;
> +	drmModeModeInfoPtr modes;
> +	int count_modes;
> +	int i;
> +	igt_output_t *output;
> +	enum pipe pipe;
> +
> +	chamelium_unplug(chamelium, port);
> +	set_edid(data, port, IGT_CUSTOM_EDID_FULL);
> +
> +	igt_flush_uevents(mon);
> +	chamelium_plug(chamelium, port);
> +	wait_for_connector_after_hotplug(data, mon, port, DRM_MODE_CONNECTED);
> +	igt_flush_uevents(mon);
> +
> +	init_connector = chamelium_port_get_connector(chamelium, port, true);
> +	modes = init_connector->modes;
> +	count_modes = init_connector->count_modes;
> +
> +	output = get_output_for_port(data, port);
> +	pipe = get_pipe_for_output(&data->display, output);
> +	igt_output_set_pipe(output, pipe);
> +
> +	for (i = 0; i < count_modes; ++i)
> +		igt_debug("#%d %s %uHz\n", i, modes[i].name, modes[i].vrefresh);
> +
> +	for (i = 0; i < count_modes; ++i) {
> +		struct chamelium_edid *chamelium_edid;
> +		struct igt_fb fb = { 0 };
> +		bool is_video_stable;
> +		int screen_res_w, screen_res_h;
> +		drmModeConnector *connector;
> +		drmModeModeInfoPtr expected_mode;
> +		bool is_same_mode;
> +
> +		igt_info("Testing #%d %s %uHz\n", i, modes[i].name,
> +			 modes[i].vrefresh);
> +
> +		/* Set the screen mode with the one we chose. */
> +		create_fb_for_mode(data, &fb, &modes[i]);
> +		enable_output(data, port, output, &modes[i], &fb);
> +		is_video_stable = chamelium_port_wait_video_input_stable(
> +			chamelium, port, 10);
> +		igt_assert(is_video_stable);
> +
> +		chamelium_port_get_resolution(chamelium, port, &screen_res_w,
> +					      &screen_res_h);
> +		igt_assert(screen_res_w == modes[i].hdisplay);
> +		igt_assert(screen_res_h == modes[i].vdisplay);

Use igt_assert_eq for == comparison.


-- 
Petri Latvala


> +
> +		igt_remove_fb(data->drm_fd, &fb);
> +	}
> +
> +	igt_modeset_disable_all_outputs(&data->display);
> +	drmModeFreeConnector(init_connector);
> +}
> +
>  #define for_each_port(p, port)            \
>  	for (p = 0, port = data.ports[p]; \
>  	     p < data.port_count;         \
> @@ -2714,6 +2778,10 @@ igt_main
>  			edid_stress_resolution(&data, port, DP_EDIDS_NON_4K,
>  					       ARRAY_SIZE(DP_EDIDS_NON_4K));
>  
> +		igt_describe(igt_edid_resolution_list_desc);
> +		connector_subtest("dp-edid-resolution-list", DisplayPort)
> +			edid_resolution_list(&data, port);
> +
>  		igt_describe(test_suspend_resume_hpd_desc);
>  		connector_subtest("dp-hpd-after-suspend", DisplayPort)
>  			test_suspend_resume_hpd(&data, port,
> -- 
> 2.38.1.431.g37b22c650d-goog
> 


More information about the igt-dev mailing list