]> git.ipfire.org Git - thirdparty/plymouth.git/commitdiff
drm: Reset mode on display-port connected outputs with a bad link-status
authorHans de Goede <hdegoede@redhat.com>
Thu, 17 Jan 2019 10:41:46 +0000 (11:41 +0100)
committerHans de Goede <hdegoede@redhat.com>
Thu, 17 Jan 2019 13:37:57 +0000 (14:37 +0100)
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 <hdegoede@redhat.com>
src/plugins/renderers/drm/plugin.c

index b190737e10164233dd58db9d40140d5d0fa2a7c8..cb228f60348051d0d0993a3dce8ca8b01993e625 100644 (file)
@@ -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)