]> git.proxmox.com Git - mirror_ubuntu-eoan-kernel.git/commitdiff
drm/rockchip: Disallow PSR for the whole atomic commit
authorTomasz Figa <tfiga@chromium.org>
Mon, 23 Apr 2018 10:50:02 +0000 (12:50 +0200)
committerAndrzej Hajda <a.hajda@samsung.com>
Tue, 24 Apr 2018 06:34:53 +0000 (08:34 +0200)
Currently PSR flush is triggered from CRTC's .atomic_begin() callback,
which is executed after modeset disables and enables and before plane
updates are committed. Since PSR flush and re-enable can be triggered
asynchronously by external sources (input event, delayed work), it can
race with hardware programming done in the aforementioned stages.

This patch blocks the PSR completely before hardware programming part
begins and unblock after it ends. This relies on reference counted PSR
disable introduced with previous patch.

Cc: Kristian H. Kristensen <hoegsberg@chromium.org>
Signed-off-by: Tomasz Figa <tfiga@chromium.org>
Signed-off-by: Sean Paul <seanpaul@chromium.org>
Signed-off-by: Thierry Escande <thierry.escande@collabora.com>
Signed-off-by: Enric Balletbo i Serra <enric.balletbo@collabora.com>
Tested-by: Marek Szyprowski <m.szyprowski@samsung.com>
Reviewed-by: Andrzej Hajda <a.hajda@samsung.com>
Signed-off-by: Andrzej Hajda <a.hajda@samsung.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20180423105003.9004-27-enric.balletbo@collabora.com
drivers/gpu/drm/rockchip/rockchip_drm_fb.c
drivers/gpu/drm/rockchip/rockchip_drm_vop.c

index e266539e04e5cc12a986f4250afa3b03d4127513..d4f4118b482ddd6f215eba1cb54d1f4dd5c83b3e 100644 (file)
@@ -167,8 +167,67 @@ err_gem_object_unreference:
        return ERR_PTR(ret);
 }
 
+static void
+rockchip_drm_psr_inhibit_get_state(struct drm_atomic_state *state)
+{
+       struct drm_crtc *crtc;
+       struct drm_crtc_state *crtc_state;
+       struct drm_encoder *encoder;
+       u32 encoder_mask = 0;
+       int i;
+
+       for_each_old_crtc_in_state(state, crtc, crtc_state, i) {
+               encoder_mask |= crtc_state->encoder_mask;
+               encoder_mask |= crtc->state->encoder_mask;
+       }
+
+       drm_for_each_encoder_mask(encoder, state->dev, encoder_mask)
+               rockchip_drm_psr_inhibit_get(encoder);
+}
+
+static void
+rockchip_drm_psr_inhibit_put_state(struct drm_atomic_state *state)
+{
+       struct drm_crtc *crtc;
+       struct drm_crtc_state *crtc_state;
+       struct drm_encoder *encoder;
+       u32 encoder_mask = 0;
+       int i;
+
+       for_each_old_crtc_in_state(state, crtc, crtc_state, i) {
+               encoder_mask |= crtc_state->encoder_mask;
+               encoder_mask |= crtc->state->encoder_mask;
+       }
+
+       drm_for_each_encoder_mask(encoder, state->dev, encoder_mask)
+               rockchip_drm_psr_inhibit_put(encoder);
+}
+
+static void
+rockchip_atomic_helper_commit_tail_rpm(struct drm_atomic_state *old_state)
+{
+       struct drm_device *dev = old_state->dev;
+
+       rockchip_drm_psr_inhibit_get_state(old_state);
+
+       drm_atomic_helper_commit_modeset_disables(dev, old_state);
+
+       drm_atomic_helper_commit_modeset_enables(dev, old_state);
+
+       drm_atomic_helper_commit_planes(dev, old_state,
+                                       DRM_PLANE_COMMIT_ACTIVE_ONLY);
+
+       rockchip_drm_psr_inhibit_put_state(old_state);
+
+       drm_atomic_helper_commit_hw_done(old_state);
+
+       drm_atomic_helper_wait_for_vblanks(dev, old_state);
+
+       drm_atomic_helper_cleanup_planes(dev, old_state);
+}
+
 static const struct drm_mode_config_helper_funcs rockchip_mode_config_helpers = {
-       .atomic_commit_tail = drm_atomic_helper_commit_tail_rpm,
+       .atomic_commit_tail = rockchip_atomic_helper_commit_tail_rpm,
 };
 
 static const struct drm_mode_config_funcs rockchip_drm_mode_config_funcs = {
index 026df454a5d54d4a920ea7fe167e4e34894ccae6..fe3faa7c38d993234311890e66af26c39a1f0e76 100644 (file)
@@ -1029,16 +1029,9 @@ static void vop_crtc_atomic_flush(struct drm_crtc *crtc,
        }
 }
 
-static void vop_crtc_atomic_begin(struct drm_crtc *crtc,
-                                 struct drm_crtc_state *old_crtc_state)
-{
-       rockchip_drm_psr_flush(crtc);
-}
-
 static const struct drm_crtc_helper_funcs vop_crtc_helper_funcs = {
        .mode_fixup = vop_crtc_mode_fixup,
        .atomic_flush = vop_crtc_atomic_flush,
-       .atomic_begin = vop_crtc_atomic_begin,
        .atomic_enable = vop_crtc_atomic_enable,
        .atomic_disable = vop_crtc_atomic_disable,
 };