[PATCH v1 1/4] drm/ast: Only set format registers if primary plane's format changes

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



The atomic modesetting code tried to distinguish format changes from
full modesetting operations. But the implementation was buggy and the
format registers were often updated even for simple pageflips.

Fix this problem by distinguishing between format and mode changes; and
handle each in it's own branch.

Signed-off-by: Thomas Zimmermann <tzimmermann@xxxxxxx>
Fixes: 4961eb60f145 ("drm/ast: Enable atomic modesetting")
Cc: Thomas Zimmermann <tzimmermann@xxxxxxx>
Cc: Gerd Hoffmann <kraxel@xxxxxxxxxx>
Cc: Dave Airlie <airlied@xxxxxxxxxx>
Cc: Daniel Vetter <daniel.vetter@xxxxxxxx>
Cc: Sam Ravnborg <sam@xxxxxxxxxxxx>
Cc: Emil Velikov <emil.l.velikov@xxxxxxxxx>
Cc: "Y.C. Chen" <yc_chen@xxxxxxxxxxxxxx>
Cc: <stable@xxxxxxxxxxxxxxx> # v5.6+
---
 drivers/gpu/drm/ast/ast_mode.c | 52 ++++++++++++++++------------------
 1 file changed, 25 insertions(+), 27 deletions(-)

diff --git a/drivers/gpu/drm/ast/ast_mode.c b/drivers/gpu/drm/ast/ast_mode.c
index 62fe682a7de6..b129833c0821 100644
--- a/drivers/gpu/drm/ast/ast_mode.c
+++ b/drivers/gpu/drm/ast/ast_mode.c
@@ -768,34 +768,32 @@ static void ast_crtc_helper_atomic_flush(struct drm_crtc *crtc,
 {
 	struct drm_device *dev = crtc->dev;
 	struct ast_private *ast = to_ast_private(dev);
-	struct ast_crtc_state *ast_state;
-	const struct drm_format_info *format;
-	struct ast_vbios_mode_info *vbios_mode_info;
-	struct drm_display_mode *adjusted_mode;
-
-	ast_state = to_ast_crtc_state(crtc->state);
-
-	format = ast_state->format;
-	if (!format)
-		return;
-
-	vbios_mode_info = &ast_state->vbios_mode_info;
-
-	ast_set_color_reg(ast, format);
-	ast_set_vbios_color_reg(ast, format, vbios_mode_info);
-
-	if (!crtc->state->mode_changed)
-		return;
-
-	adjusted_mode = &crtc->state->adjusted_mode;
+	struct drm_crtc_state *crtc_state = crtc->state;
+	struct ast_crtc_state *ast_crtc_state = to_ast_crtc_state(crtc_state);
+	struct ast_crtc_state *old_ast_crtc_state =
+		to_ast_crtc_state(old_crtc_state);
+	const struct drm_format_info *format = ast_crtc_state->format;
+	struct ast_vbios_mode_info *vbios_mode_info =
+		&ast_crtc_state->vbios_mode_info;
+	struct drm_display_mode *adjusted_mode = &crtc_state->adjusted_mode;
+
+	if (drm_WARN_ON_ONCE(dev, !format))
+		return; /* BUG: We didn't set format in primary check(). */
+
+	if (format != old_ast_crtc_state->format) {
+		ast_set_color_reg(ast, format);
+		ast_set_vbios_color_reg(ast, format, vbios_mode_info);
+	}
 
-	ast_set_vbios_mode_reg(ast, adjusted_mode, vbios_mode_info);
-	ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xa1, 0x06);
-	ast_set_std_reg(ast, adjusted_mode, vbios_mode_info);
-	ast_set_crtc_reg(ast, adjusted_mode, vbios_mode_info);
-	ast_set_dclk_reg(ast, adjusted_mode, vbios_mode_info);
-	ast_set_crtthd_reg(ast);
-	ast_set_sync_reg(ast, adjusted_mode, vbios_mode_info);
+	if (drm_atomic_crtc_needs_modeset(crtc_state)) {
+		ast_set_vbios_mode_reg(ast, adjusted_mode, vbios_mode_info);
+		ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xa1, 0x06);
+		ast_set_std_reg(ast, adjusted_mode, vbios_mode_info);
+		ast_set_crtc_reg(ast, adjusted_mode, vbios_mode_info);
+		ast_set_dclk_reg(ast, adjusted_mode, vbios_mode_info);
+		ast_set_crtthd_reg(ast);
+		ast_set_sync_reg(ast, adjusted_mode, vbios_mode_info);
+	}
 }
 
 static void
-- 
2.28.0




[Index of Archives]     [Linux Kernel]     [Kernel Development Newbies]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite Hiking]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux