OSDN Git Service

drm/ast: Store primary-plane format in struct ast_crtc_state
authorThomas Zimmermann <tzimmermann@suse.de>
Mon, 2 Dec 2019 11:15:57 +0000 (12:15 +0100)
committerThomas Zimmermann <tzimmermann@suse.de>
Tue, 10 Dec 2019 13:28:43 +0000 (14:28 +0100)
Reading the primary plane's framebuffer from the CRTC's atomic_flush()
function is fragile as the plane state or framebuffer can be NULL.
Instead, we let the plane's atomic_check() store the framebuffer format
in the CRTC state. The CRTC always receives the framebuffer format that
is currently programmed, or NULL if no mode has been set yet.

Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
Acked-by: Gerd Hoffmann <kraxel@redhat.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20191202111557.15176-8-tzimmermann@suse.de
drivers/gpu/drm/ast/ast_drv.h
drivers/gpu/drm/ast/ast_mode.c

index 72883b5..f5d8780 100644 (file)
@@ -284,6 +284,9 @@ struct ast_vbios_mode_info {
 struct ast_crtc_state {
        struct drm_crtc_state base;
 
+       /* Last known format of primary plane */
+       const struct drm_format_info *format;
+
        struct ast_vbios_mode_info vbios_mode_info;
 };
 
index a277248..cde1cae 100644 (file)
@@ -535,6 +535,7 @@ static int ast_primary_plane_helper_atomic_check(struct drm_plane *plane,
                                                 struct drm_plane_state *state)
 {
        struct drm_crtc_state *crtc_state;
+       struct ast_crtc_state *ast_crtc_state;
        int ret;
 
        if (!state->crtc)
@@ -549,6 +550,13 @@ static int ast_primary_plane_helper_atomic_check(struct drm_plane *plane,
        if (ret)
                return ret;
 
+       if (!state->visible)
+               return 0;
+
+       ast_crtc_state = to_ast_crtc_state(crtc_state);
+
+       ast_crtc_state->format = state->fb->format;
+
        return 0;
 }
 
@@ -783,8 +791,8 @@ static int ast_crtc_helper_atomic_check(struct drm_crtc *crtc,
                                        struct drm_crtc_state *state)
 {
        struct ast_private *ast = crtc->dev->dev_private;
-       struct drm_plane_state *plane_state;
        struct ast_crtc_state *ast_state;
+       const struct drm_format_info *format;
        bool succ;
 
        if (ast->chip == AST1180) {
@@ -793,12 +801,12 @@ static int ast_crtc_helper_atomic_check(struct drm_crtc *crtc,
        }
 
        ast_state = to_ast_crtc_state(state);
-       plane_state = crtc->primary->state;
 
-       if (!plane_state || !plane_state->fb)
+       format = ast_state->format;
+       if (!format)
                return 0;
 
-       succ = ast_get_vbios_mode_info(plane_state->fb->format, &state->mode,
+       succ = ast_get_vbios_mode_info(format, &state->mode,
                                       &state->adjusted_mode,
                                       &ast_state->vbios_mode_info);
        if (!succ)
@@ -820,7 +828,6 @@ static void ast_crtc_helper_atomic_flush(struct drm_crtc *crtc,
 {
        struct drm_device *dev = crtc->dev;
        struct ast_private *ast = dev->dev_private;
-       const struct drm_framebuffer *fb = crtc->primary->state->fb;
        struct ast_crtc_state *ast_state;
        const struct drm_format_info *format;
        struct ast_vbios_mode_info *vbios_mode_info;
@@ -828,12 +835,12 @@ static void ast_crtc_helper_atomic_flush(struct drm_crtc *crtc,
 
        crtc->state->no_vblank = true;
 
-       if (!fb)
-               return;
-
        ast_state = to_ast_crtc_state(crtc->state);
 
-       format = fb->format;
+       format = ast_state->format;
+       if (!format)
+               return;
+
        vbios_mode_info = &ast_state->vbios_mode_info;
 
        ast_set_color_reg(ast, format);
@@ -896,6 +903,7 @@ ast_crtc_atomic_duplicate_state(struct drm_crtc *crtc)
 
        ast_state = to_ast_crtc_state(crtc->state);
 
+       new_ast_state->format = ast_state->format;
        memcpy(&new_ast_state->vbios_mode_info, &ast_state->vbios_mode_info,
               sizeof(new_ast_state->vbios_mode_info));