From: Hans de Goede Date: Thu, 17 Jan 2019 10:41:46 +0000 (+0100) Subject: drm: Reset mode on display-port connected outputs with a bad link-status X-Git-Tag: 0.9.5~76^2~3 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=c54870fc6663b010b2a3eb4a44df5dd41dd7011c;p=thirdparty%2Fplymouth.git drm: Reset mode on display-port connected outputs with a bad link-status With Display-Port links, esp. with DP MST links we may need to reset the mode if the kernel decides to retrain the link. If the kernel has retrained the link, the list of available modes may have changed. If it changed and the mode we picked is no longer available because of this, we treat this as an unplug + replug. Since we may want to set another mode, the kernel does not automatically restore the previous mode. So in case the mode did not change we need to do an explicit mode-set. This commits adds support for this, by: 1) Adding a scan_out_buffer_needs_reset member to ply_renderer_head 2) Storing the link-status when going over the connector properties 3) Checking the link-status when adding a connector to a head and setting the scan_out_buffer_needs_reset flag when the link-status is bad This commit also makes ply_renderer_head_map set scan_out_buffer_needs_reset, avoiding an unnecessary round-trip to the kernel in the first reset_scan_out_buffer_if_needed call. Signed-off-by: Hans de Goede --- diff --git a/src/plugins/renderers/drm/plugin.c b/src/plugins/renderers/drm/plugin.c index b190737e..cb228f60 100644 --- a/src/plugins/renderers/drm/plugin.c +++ b/src/plugins/renderers/drm/plugin.c @@ -82,6 +82,7 @@ struct _ply_renderer_head uint32_t controller_id; uint32_t console_buffer_id; uint32_t scan_out_buffer_id; + bool scan_out_buffer_needs_reset; int gamma_size; uint16_t *gamma; @@ -122,6 +123,7 @@ typedef struct uint32_t controller_id; uint32_t possible_controllers; int device_scale; + int link_status; ply_pixel_buffer_rotation_t rotation; bool tiled; bool connected; @@ -473,6 +475,12 @@ ply_renderer_connector_get_rotation_and_tiled (ply_renderer_backend_t *back strcmp (prop->name, "TILE") == 0) output->tiled = true; + if ((prop->flags & DRM_MODE_PROP_ENUM) && + strcmp (prop->name, "link-status") == 0) { + output->link_status = connector->prop_values[i]; + ply_trace ("link-status %d", output->link_status); + } + drmModeFreeProperty (prop); } } @@ -481,6 +489,9 @@ static bool ply_renderer_head_add_connector (ply_renderer_head_t *head, ply_output_t *output) { + if (output->link_status == DRM_MODE_LINK_STATUS_BAD) + head->scan_out_buffer_needs_reset = true; + if (output->mode.hdisplay != head->area.width || output->mode.vdisplay != head->area.height) { ply_trace ("Tried to add connector with resolution %dx%d to %dx%d head", (int) output->mode.hdisplay, (int) output->mode.vdisplay, @@ -715,6 +726,7 @@ ply_renderer_head_map (ply_renderer_backend_t *backend, return false; } + head->scan_out_buffer_needs_reset = true; return true; } @@ -1589,6 +1601,13 @@ reset_scan_out_buffer_if_needed (ply_renderer_backend_t *backend, if (!ply_terminal_is_active (backend->terminal)) return false; + if (head->scan_out_buffer_needs_reset) { + ply_renderer_head_set_scan_out_buffer (backend, head, + head->scan_out_buffer_id); + head->scan_out_buffer_needs_reset = false; + return true; + } + controller = drmModeGetCrtc (backend->device_fd, head->controller_id); if (controller == NULL)