@@ -138,3 +138,37 @@ bool igt_psr_valid_connector(drmModeConnectorPtr connector)
{
return (connector->connector_type == DRM_MODE_CONNECTOR_eDP);
}
+
+/**
+ * igt_psr_find_good_mode
+ * @connector: a drmModeConnector pointer to find the mode on
+ * @mode: a drmModeModePtr pointer that is set to the matching mode
+ *
+ * Returns true (and populates *mode with the match) if a valid
+ * PSR mdoe is found, and false otherwise.
+ */
+bool igt_psr_find_good_mode(drmModeConnectorPtr connector,
+ drmModeModeInfoPtr *mode)
+{
+ int i;
+
+ if (!connector->count_modes) {
+ igt_warn("no modes for connector %d.\n",
+ connector->connector_id);
+ return false;
+ } else {
+ igt_debug("Connector has %d modes.\n", connector->count_modes);
+ }
+
+ for (i = 0; i < connector->count_modes; i++) {
+ if ((connector->modes[i].vtotal -
+ connector->modes[i].vdisplay) >= 36) {
+ igt_debug("Mode %d good for PSR.\n", i);
+ *mode = &(connector->modes[i]);
+ return true;
+ } else {
+ igt_debug("Throwing out mode %d\n", i);
+ }
+ }
+ return false;
+}
@@ -34,5 +34,7 @@ bool igt_psr_active(int fd);
bool igt_psr_await_status(int fd, bool active);
void igt_psr_print_status(int fd);
bool igt_psr_valid_connector(drmModeConnectorPtr connector);
+bool igt_psr_find_good_mode(drmModeConnectorPtr connector,
+ drmModeModeInfoPtr *mode);
#endif /* IGT_PSR_H */
@@ -125,6 +125,10 @@ static void set_mode_for_one_screen(struct drm_info *drm, struct igt_fb *fb,
if (c->connection == DRM_MODE_CONNECTED && c->count_modes &&
connector_possible(c)) {
+ if (c->connector_type == DRM_MODE_CONNECTOR_eDP) {
+ if (igt_psr_find_good_mode(c, &mode))
+ break;
+ }
mode = &c->modes[0];
break;
}
@@ -435,7 +435,7 @@ static bool connector_get_mode(drmModeConnectorPtr c, drmModeModeInfoPtr *mode)
if (opt.small_modes)
*mode = get_connector_smallest_mode(c);
else
- *mode = &c->modes[0];
+ igt_assert(igt_psr_find_good_mode(c, mode));
return true;
}
@@ -70,7 +70,7 @@ typedef struct {
uint32_t crtc_id;
igt_display_t display;
drm_intel_bufmgr *bufmgr;
- struct igt_fb fb_green, fb_white;
+ struct igt_fb fb_green, fb_white, fb_blue;
igt_plane_t *primary, *sprite, *cursor;
int mod_size;
int mod_stride;
@@ -99,6 +99,7 @@ static void setup_output(data_t *data)
igt_display_t *display = &data->display;
igt_output_t *output;
enum pipe pipe;
+ drmModeModeInfoPtr mode = NULL;
for_each_pipe_with_valid_output(display, pipe, output) {
drmModeConnectorPtr c = output->config.connector;
@@ -106,10 +107,14 @@ static void setup_output(data_t *data)
if (!igt_psr_valid_connector(c))
continue;
+ if (!igt_psr_find_good_mode(c, &mode))
+ continue;
+ igt_assert(mode != NULL);
+ igt_output_override_mode(output, mode);
igt_output_set_pipe(output, pipe);
data->crtc_id = output->config.crtc->crtc_id;
data->output = output;
- data->mode = igt_output_get_mode(output);
+ data->mode = &output->override_mode;
return;
}
@@ -119,10 +124,33 @@ static void display_init(data_t *data)
{
igt_display_init(&data->display, data->drm_fd);
setup_output(data);
+
+ /* We need to be able to do a modeset before we enable PSR to
+ * ensure that we are running at a mode such that PSR setup can
+ * complete within a single vblank interval.
+ */
+ igt_debug("Selected mode:\n");
+ kmstest_dump_mode(data->mode);
+ igt_create_color_fb(data->drm_fd,
+ data->mode->hdisplay, data->mode->vdisplay,
+ DRM_FORMAT_XRGB8888,
+ LOCAL_I915_FORMAT_MOD_X_TILED,
+ 0.0, .0, 1.0,
+ &data->fb_blue);
+
+ data->primary = igt_output_get_plane_type(data->output,
+ DRM_PLANE_TYPE_PRIMARY);
+ igt_plane_set_fb(data->primary, &data->fb_blue);
+ igt_display_commit(&data->display);
+ if (running_with_psr_disabled)
+ igt_psr_disable();
+ else
+ igt_psr_enable();
}
static void display_fini(data_t *data)
{
+ igt_output_override_mode(data->output, NULL);
igt_display_fini(&data->display);
}
@@ -487,19 +515,12 @@ int main(int argc, char *argv[])
data.drm_fd = drm_open_driver_master(DRIVER_INTEL);
kmstest_set_vt_graphics_mode();
data.devid = intel_get_drm_devid(data.drm_fd);
-
- if (running_with_psr_disabled)
- igt_psr_disable();
- else
- igt_psr_enable();
-
- igt_skip_on(!psr_possible(&data));
-
data.bufmgr = drm_intel_bufmgr_gem_init(data.drm_fd, 4096);
igt_assert(data.bufmgr);
drm_intel_bufmgr_gem_enable_reuse(data.bufmgr);
display_init(&data);
+ igt_skip_on(!psr_possible(&data));
}
igt_subtest("psr_basic") {
Signed-off-by: Jim Bride <jim.bride@linux.intel.com> --- lib/igt_psr.c | 34 +++++++++++++++++++++++++++++++++ lib/igt_psr.h | 2 ++ tests/kms_fbcon_fbt.c | 4 ++++ tests/kms_frontbuffer_tracking.c | 2 +- tests/kms_psr_sink_crc.c | 41 ++++++++++++++++++++++++++++++---------- 5 files changed, 72 insertions(+), 11 deletions(-)