summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/igt_kms.c2
-rw-r--r--lib/igt_kms.h1
-rw-r--r--tests/kms_chamelium.c315
3 files changed, 216 insertions, 102 deletions
diff --git a/lib/igt_kms.c b/lib/igt_kms.c
index 7f9fafb3..e9621e7e 100644
--- a/lib/igt_kms.c
+++ b/lib/igt_kms.c
@@ -1666,7 +1666,7 @@ static void igt_display_log_shift(igt_display_t *display, int shift)
igt_assert(display->log_shift >= 0);
}
-static void igt_output_refresh(igt_output_t *output)
+void igt_output_refresh(igt_output_t *output)
{
igt_display_t *display = output->display;
unsigned long crtc_idx_mask = 0;
diff --git a/lib/igt_kms.h b/lib/igt_kms.h
index cd3fdbc0..adca59ac 100644
--- a/lib/igt_kms.h
+++ b/lib/igt_kms.h
@@ -423,6 +423,7 @@ igt_plane_t *igt_output_get_plane_type_index(igt_output_t *output,
int plane_type, int index);
igt_output_t *igt_output_from_connector(igt_display_t *display,
drmModeConnector *connector);
+void igt_output_refresh(igt_output_t *output);
const drmModeModeInfo *igt_std_1024_mode_get(void);
igt_plane_t *igt_pipe_get_plane_type(igt_pipe_t *pipe, int plane_type);
diff --git a/tests/kms_chamelium.c b/tests/kms_chamelium.c
index 63ae077d..8b20bbbc 100644
--- a/tests/kms_chamelium.c
+++ b/tests/kms_chamelium.c
@@ -45,6 +45,12 @@ enum test_edid {
};
#define TEST_EDID_COUNT 5
+enum test_modeset_mode {
+ TEST_MODESET_ON,
+ TEST_MODESET_ON_OFF,
+ TEST_MODESET_OFF,
+};
+
typedef struct {
struct chamelium *chamelium;
struct chamelium_port **ports;
@@ -111,12 +117,17 @@ reprobe_connector(data_t *data, struct chamelium_port *port)
{
drmModeConnector *connector;
drmModeConnection status;
+ igt_output_t *output;
igt_debug("Reprobing %s...\n", chamelium_port_get_name(port));
connector = chamelium_port_get_connector(data->chamelium, port, true);
igt_assert(connector);
status = connector->connection;
+ /* let's make sure that igt_display is up to date too */
+ output = igt_output_from_connector(&data->display, connector);
+ igt_output_refresh(output);
+
drmModeFreeConnector(connector);
return status;
}
@@ -294,14 +305,140 @@ reset_state(data_t *data, struct chamelium_port *port)
}
}
+static void chamelium_paint_xr24_pattern(uint32_t *data,
+ size_t width, size_t height,
+ size_t stride, size_t block_size)
+{
+ uint32_t colors[] = { 0xff000000,
+ 0xffff0000,
+ 0xff00ff00,
+ 0xff0000ff,
+ 0xffffffff };
+ unsigned i, j;
+
+ for (i = 0; i < height; i++)
+ for (j = 0; j < width; j++)
+ *(data + i * stride / 4 + j) = colors[((j / block_size) + (i / block_size)) % 5];
+}
+
+static int chamelium_get_pattern_fb(data_t *data, size_t width, size_t height,
+ uint32_t fourcc, size_t block_size,
+ struct igt_fb *fb)
+{
+ int fb_id;
+ void *ptr;
+
+ igt_assert(fourcc == DRM_FORMAT_XRGB8888);
+
+ fb_id = igt_create_fb(data->drm_fd, width, height, fourcc,
+ LOCAL_DRM_FORMAT_MOD_NONE, fb);
+ igt_assert(fb_id > 0);
+
+ ptr = igt_fb_map_buffer(fb->fd, fb);
+ igt_assert(ptr);
+
+ chamelium_paint_xr24_pattern(ptr, width, height, fb->strides[0],
+ block_size);
+ igt_fb_unmap_buffer(fb, ptr);
+
+ return fb_id;
+}
+
+static void
+enable_output(data_t *data,
+ struct chamelium_port *port,
+ igt_output_t *output,
+ drmModeModeInfo *mode,
+ struct igt_fb *fb)
+{
+ igt_display_t *display = output->display;
+ igt_plane_t *primary = igt_output_get_plane_type(output, DRM_PLANE_TYPE_PRIMARY);
+ drmModeConnector *connector = chamelium_port_get_connector(
+ data->chamelium, port, false);
+
+ igt_assert(primary);
+
+ igt_plane_set_size(primary, mode->hdisplay, mode->vdisplay);
+ igt_plane_set_fb(primary, fb);
+ igt_output_override_mode(output, mode);
+
+ /* Clear any color correction values that might be enabled */
+ if (igt_pipe_obj_has_prop(primary->pipe, IGT_CRTC_DEGAMMA_LUT))
+ igt_pipe_obj_replace_prop_blob(primary->pipe, IGT_CRTC_DEGAMMA_LUT, NULL, 0);
+ if (igt_pipe_obj_has_prop(primary->pipe, IGT_CRTC_GAMMA_LUT))
+ igt_pipe_obj_replace_prop_blob(primary->pipe, IGT_CRTC_GAMMA_LUT, NULL, 0);
+ if (igt_pipe_obj_has_prop(primary->pipe, IGT_CRTC_CTM))
+ igt_pipe_obj_replace_prop_blob(primary->pipe, IGT_CRTC_CTM, NULL, 0);
+
+ igt_display_commit2(display, COMMIT_ATOMIC);
+
+ if (chamelium_port_get_type(port) == DRM_MODE_CONNECTOR_VGA)
+ usleep(250000);
+
+ drmModeFreeConnector(connector);
+}
+
+static enum pipe get_pipe_for_output(igt_display_t *display, igt_output_t *output)
+{
+ enum pipe pipe;
+
+ for_each_pipe(display, pipe) {
+ if (igt_pipe_connector_valid(pipe, output)) {
+ return pipe;
+ }
+ }
+
+ igt_assert_f(false, "No pipe found for output %s\n",
+ igt_output_name(output));
+}
+
+static void create_fb_for_mode(data_t *data, struct igt_fb *fb, drmModeModeInfo *mode)
+{
+ int fb_id;
+
+ fb_id = chamelium_get_pattern_fb(data, mode->hdisplay, mode->vdisplay,
+ DRM_FORMAT_XRGB8888, 64, fb);
+
+ igt_assert(fb_id > 0);
+}
+
+static drmModeModeInfo get_mode_for_port(struct chamelium *chamelium,
+ struct chamelium_port *port)
+{
+ drmModeConnector *connector = chamelium_port_get_connector(chamelium,
+ port, false);
+ drmModeModeInfo mode;
+ igt_assert(&connector->modes[0] != NULL);
+ memcpy(&mode, &connector->modes[0], sizeof(mode));
+ drmModeFreeConnector(connector);
+ return mode;
+}
+
+static igt_output_t *get_output_for_port(data_t *data,
+ struct chamelium_port *port)
+{
+ drmModeConnector *connector = chamelium_port_get_connector(data->chamelium,
+ port, false);
+ igt_output_t *output = igt_output_from_connector(&data->display,
+ connector);
+ drmModeFreeConnector(connector);
+ igt_assert(output != NULL);
+ return output;
+}
+
static const char test_basic_hotplug_desc[] =
"Check that we get uevents and updated connector status on "
"hotplug and unplug";
static void
-test_basic_hotplug(data_t *data, struct chamelium_port *port, int toggle_count)
+test_hotplug(data_t *data, struct chamelium_port *port, int toggle_count,
+ enum test_modeset_mode modeset_mode)
{
- struct udev_monitor *mon = igt_watch_hotplug();
int i;
+ enum pipe pipe;
+ struct igt_fb fb = {0};
+ drmModeModeInfo mode;
+ struct udev_monitor *mon = igt_watch_hotplug();
+ igt_output_t *output = get_output_for_port(data, port);
reset_state(data, NULL);
igt_hpd_storm_set_threshold(data->drm_fd, 0);
@@ -316,15 +453,36 @@ test_basic_hotplug(data_t *data, struct chamelium_port *port, int toggle_count)
DRM_MODE_CONNECTED);
igt_flush_hotplugs(mon);
+ if (modeset_mode == TEST_MODESET_ON_OFF ||
+ (modeset_mode == TEST_MODESET_ON && i == 0 )) {
+ if (i == 0) {
+ /* We can only get mode and pipe once we are connected */
+ pipe = get_pipe_for_output(&data->display, output);
+ mode = get_mode_for_port(data->chamelium, port);
+ create_fb_for_mode(data, &fb, &mode);
+ }
+
+ igt_output_set_pipe(output, pipe);
+ enable_output(data, port, output, &mode, &fb);
+ }
+
/* Now check if we get a hotplug from disconnection */
chamelium_unplug(data->chamelium, port);
wait_for_connector_after_hotplug(data, mon, port,
DRM_MODE_DISCONNECTED);
+
+ igt_flush_hotplugs(mon);
+
+ if (modeset_mode == TEST_MODESET_ON_OFF) {
+ igt_output_set_pipe(output, PIPE_NONE);
+ igt_display_commit2(&data->display, COMMIT_ATOMIC);
+ }
}
igt_cleanup_hotplug(mon);
igt_hpd_storm_reset(data->drm_fd);
+ igt_remove_fb(data->drm_fd, &fb);
}
static const struct edid *get_edid(enum test_edid edid);
@@ -530,10 +688,7 @@ prepare_output(data_t *data, struct chamelium_port *port, enum test_edid edid)
{
igt_display_t *display = &data->display;
igt_output_t *output;
- drmModeConnector *connector =
- chamelium_port_get_connector(data->chamelium, port, false);
enum pipe pipe;
- bool found = false;
/* The chamelium's default EDID has a lot of resolutions, way more then
* we need to test. Additionally the default EDID doesn't support HDMI
@@ -546,101 +701,17 @@ prepare_output(data_t *data, struct chamelium_port *port, enum test_edid edid)
igt_display_reset(display);
- output = igt_output_from_connector(display, connector);
+ output = get_output_for_port(data, port);
/* Refresh pipe to update connected status */
igt_output_set_pipe(output, PIPE_NONE);
- for_each_pipe(display, pipe) {
- if (!igt_pipe_connector_valid(pipe, output))
- continue;
-
- found = true;
- break;
- }
-
- igt_assert_f(found, "No pipe found for output %s\n", igt_output_name(output));
-
+ pipe = get_pipe_for_output(display, output);
igt_output_set_pipe(output, pipe);
- drmModeFreeConnector(connector);
-
return output;
}
-static void
-enable_output(data_t *data,
- struct chamelium_port *port,
- igt_output_t *output,
- drmModeModeInfo *mode,
- struct igt_fb *fb)
-{
- igt_display_t *display = output->display;
- igt_plane_t *primary = igt_output_get_plane_type(output, DRM_PLANE_TYPE_PRIMARY);
- drmModeConnector *connector = chamelium_port_get_connector(
- data->chamelium, port, false);
-
- igt_assert(primary);
-
- igt_plane_set_size(primary, mode->hdisplay, mode->vdisplay);
- igt_plane_set_fb(primary, fb);
- igt_output_override_mode(output, mode);
-
- /* Clear any color correction values that might be enabled */
- if (igt_pipe_obj_has_prop(primary->pipe, IGT_CRTC_DEGAMMA_LUT))
- igt_pipe_obj_replace_prop_blob(primary->pipe, IGT_CRTC_DEGAMMA_LUT, NULL, 0);
- if (igt_pipe_obj_has_prop(primary->pipe, IGT_CRTC_GAMMA_LUT))
- igt_pipe_obj_replace_prop_blob(primary->pipe, IGT_CRTC_GAMMA_LUT, NULL, 0);
- if (igt_pipe_obj_has_prop(primary->pipe, IGT_CRTC_CTM))
- igt_pipe_obj_replace_prop_blob(primary->pipe, IGT_CRTC_CTM, NULL, 0);
-
- igt_display_commit2(display, COMMIT_ATOMIC);
-
- if (chamelium_port_get_type(port) == DRM_MODE_CONNECTOR_VGA)
- usleep(250000);
-
- drmModeFreeConnector(connector);
-}
-
-static void chamelium_paint_xr24_pattern(uint32_t *data,
- size_t width, size_t height,
- size_t stride, size_t block_size)
-{
- uint32_t colors[] = { 0xff000000,
- 0xffff0000,
- 0xff00ff00,
- 0xff0000ff,
- 0xffffffff };
- unsigned i, j;
-
- for (i = 0; i < height; i++)
- for (j = 0; j < width; j++)
- *(data + i * stride / 4 + j) = colors[((j / block_size) + (i / block_size)) % 5];
-}
-
-static int chamelium_get_pattern_fb(data_t *data, size_t width, size_t height,
- uint32_t fourcc, size_t block_size,
- struct igt_fb *fb)
-{
- int fb_id;
- void *ptr;
-
- igt_assert(fourcc == DRM_FORMAT_XRGB8888);
-
- fb_id = igt_create_fb(data->drm_fd, width, height, fourcc,
- LOCAL_DRM_FORMAT_MOD_NONE, fb);
- igt_assert(fb_id > 0);
-
- ptr = igt_fb_map_buffer(fb->fd, fb);
- igt_assert(ptr);
-
- chamelium_paint_xr24_pattern(ptr, width, height, fb->strides[0],
- block_size);
- igt_fb_unmap_buffer(fb, ptr);
-
- return fb_id;
-}
-
static void do_test_display(data_t *data, struct chamelium_port *port,
igt_output_t *output, drmModeModeInfo *mode,
uint32_t fourcc, enum chamelium_check check,
@@ -2555,13 +2626,27 @@ igt_main
igt_describe(test_basic_hotplug_desc);
connector_subtest("dp-hpd", DisplayPort)
- test_basic_hotplug(&data, port,
- HPD_TOGGLE_COUNT_DP_HDMI);
+ test_hotplug(&data, port,
+ HPD_TOGGLE_COUNT_DP_HDMI,
+ TEST_MODESET_OFF);
igt_describe(test_basic_hotplug_desc);
connector_subtest("dp-hpd-fast", DisplayPort)
- test_basic_hotplug(&data, port,
- HPD_TOGGLE_COUNT_FAST);
+ test_hotplug(&data, port,
+ HPD_TOGGLE_COUNT_FAST,
+ TEST_MODESET_OFF);
+
+ igt_describe(test_basic_hotplug_desc);
+ connector_subtest("dp-hpd-enable-disable-mode", DisplayPort)
+ test_hotplug(&data, port,
+ HPD_TOGGLE_COUNT_FAST,
+ TEST_MODESET_ON_OFF);
+
+ igt_describe(test_basic_hotplug_desc);
+ connector_subtest("dp-hpd-with-enabled-mode", DisplayPort)
+ test_hotplug(&data, port,
+ HPD_TOGGLE_COUNT_FAST,
+ TEST_MODESET_ON);
igt_describe(test_edid_read_desc);
connector_subtest("dp-edid-read", DisplayPort) {
@@ -2650,13 +2735,27 @@ igt_main
igt_describe(test_basic_hotplug_desc);
connector_subtest("hdmi-hpd", HDMIA)
- test_basic_hotplug(&data, port,
- HPD_TOGGLE_COUNT_DP_HDMI);
+ test_hotplug(&data, port,
+ HPD_TOGGLE_COUNT_DP_HDMI,
+ TEST_MODESET_OFF);
igt_describe(test_basic_hotplug_desc);
connector_subtest("hdmi-hpd-fast", HDMIA)
- test_basic_hotplug(&data, port,
- HPD_TOGGLE_COUNT_FAST);
+ test_hotplug(&data, port,
+ HPD_TOGGLE_COUNT_FAST,
+ TEST_MODESET_OFF);
+
+ igt_describe(test_basic_hotplug_desc);
+ connector_subtest("hdmi-hpd-enable-disable-mode", HDMIA)
+ test_hotplug(&data, port,
+ HPD_TOGGLE_COUNT_FAST,
+ TEST_MODESET_ON_OFF);
+
+ igt_describe(test_basic_hotplug_desc);
+ connector_subtest("hdmi-hpd-with-enabled-mode", HDMIA)
+ test_hotplug(&data, port,
+ HPD_TOGGLE_COUNT_FAST,
+ TEST_MODESET_ON);
igt_describe(test_edid_read_desc);
connector_subtest("hdmi-edid-read", HDMIA) {
@@ -2811,11 +2910,25 @@ igt_main
igt_describe(test_basic_hotplug_desc);
connector_subtest("vga-hpd", VGA)
- test_basic_hotplug(&data, port, HPD_TOGGLE_COUNT_VGA);
+ test_hotplug(&data, port, HPD_TOGGLE_COUNT_VGA,
+ TEST_MODESET_OFF);
igt_describe(test_basic_hotplug_desc);
connector_subtest("vga-hpd-fast", VGA)
- test_basic_hotplug(&data, port, HPD_TOGGLE_COUNT_FAST);
+ test_hotplug(&data, port, HPD_TOGGLE_COUNT_FAST,
+ TEST_MODESET_OFF);
+
+ igt_describe(test_basic_hotplug_desc);
+ connector_subtest("vga-hpd-enable-disable-mode", VGA)
+ test_hotplug(&data, port,
+ HPD_TOGGLE_COUNT_FAST,
+ TEST_MODESET_ON_OFF);
+
+ igt_describe(test_basic_hotplug_desc);
+ connector_subtest("vga-hpd-with-enabled-mode", VGA)
+ test_hotplug(&data, port,
+ HPD_TOGGLE_COUNT_FAST,
+ TEST_MODESET_ON);
igt_describe(test_edid_read_desc);
connector_subtest("vga-edid-read", VGA) {