]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
drm/vmwgfx: Trigger a modeset when the screen moves
authorIan Forbes <ian.forbes@broadcom.com>
Mon, 24 Jun 2024 20:59:51 +0000 (15:59 -0500)
committerZack Rusin <zack.rusin@broadcom.com>
Fri, 26 Jul 2024 02:21:00 +0000 (22:21 -0400)
When multi-monitor is cycled the X,Y position of the Screen Target will
likely change but the resolution will not. We need to trigger a modeset
when this occurs in order to recreate the Screen Target with the correct
X,Y position.

Fixes a bug where multiple displays are shown in a single scrollable
host window rather than in 2+ windows on separate host displays.

Fixes: 426826933109 ("drm/vmwgfx: Filter modes which exceed graphics memory")
Signed-off-by: Ian Forbes <ian.forbes@broadcom.com>
Signed-off-by: Zack Rusin <zack.rusin@broadcom.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20240624205951.23343-1-ian.forbes@broadcom.com
drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c

index 5106413c14b71b49007954d7842afce268b50e15..5453f7cf0e2d7b05e1020743dc18dcd766617308 100644 (file)
@@ -873,6 +873,32 @@ vmw_stdu_connector_mode_valid(struct drm_connector *connector,
        return MODE_OK;
 }
 
+/*
+ * Trigger a modeset if the X,Y position of the Screen Target changes.
+ * This is needed when multi-mon is cycled. The original Screen Target will have
+ * the same mode but its relative X,Y position in the topology will change.
+ */
+static int vmw_stdu_connector_atomic_check(struct drm_connector *conn,
+                                          struct drm_atomic_state *state)
+{
+       struct drm_connector_state *conn_state;
+       struct vmw_screen_target_display_unit *du;
+       struct drm_crtc_state *new_crtc_state;
+
+       conn_state = drm_atomic_get_connector_state(state, conn);
+       du = vmw_connector_to_stdu(conn);
+
+       if (!conn_state->crtc)
+               return 0;
+
+       new_crtc_state = drm_atomic_get_new_crtc_state(state, conn_state->crtc);
+       if (du->base.gui_x != du->base.set_gui_x ||
+           du->base.gui_y != du->base.set_gui_y)
+               new_crtc_state->mode_changed = true;
+
+       return 0;
+}
+
 static const struct drm_connector_funcs vmw_stdu_connector_funcs = {
        .dpms = vmw_du_connector_dpms,
        .detect = vmw_du_connector_detect,
@@ -887,7 +913,8 @@ static const struct drm_connector_funcs vmw_stdu_connector_funcs = {
 static const struct
 drm_connector_helper_funcs vmw_stdu_connector_helper_funcs = {
        .get_modes = vmw_connector_get_modes,
-       .mode_valid = vmw_stdu_connector_mode_valid
+       .mode_valid = vmw_stdu_connector_mode_valid,
+       .atomic_check = vmw_stdu_connector_atomic_check,
 };